xmlattributesbasex

Issue with BaseX XQuery content:unable to add an attribute, and I don't know how to add tags, just know how to add values


PS- Please tell admins to enable more usability to review code indentation, the task was too rough, had to use a link and it forces a format when code formats are several ones, and i had to remove javadoc

I use to avoid asking here because i had issues already making a question about a mysql error which ended being an incomplete query at the end, but i cant manage to find documentation this time of BaseX for my studies and i have issues.

Theroretically, in the theory appears history and info of the xml native dbms and xml enabled dbms, and then appears in a summary the syntax of xquery with BaseX with syntaxes like update insert.

However, lacks how to add an attribute. The answer of my teacher is yet more confusing, becuasde hne said me that i have to modify the whole xml in a shoot, when baseX is used to modify attributes, and he mentions me a code in 'Utilitats.xml' (utils) where he uses jaxb instead, which confuses me more.

Well, the question is, which should be the right syntax to add the attribute? I add the base class, the class data handler where i have the issue in the insert method and the test file

Btw, as i've seen in similar answers-No, teacher won't let me use XPath instead.

About the nodes as said in title, i dont understand how to add the tags/nodes to add inside them the values at the same time, or otherwise how to add first the nodes and how to let the system know the new node the xquery have to insert the value in, because i didn't find how to check that a tag has no values or tags inside, and count would return me all the same tags. It's being used in a LXDE vm with Netbeans and OpenJDK 11 which was the only suitable jdk, and the API is Basex. It's hard for me to find info in the web about this since it's obsolete apparently. Also, keep in mind i didnt manage to check attempts to add nodes, probably misses the node word on them after the few documentation i found on the web .

I think the only related question was the first one appearing me and i think it didn't clearify my confusion, because it uses a for-return and i don't know how that works for show content, replace or insert.

I tried to add an attribute with xquery, but syntax documentation in basex is incomplete and i miss info in the web. I expected the attribute is added, then the nodes get added at the same time within their value in method inserir in the manager

Base class(Model)

`
package eac4.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement(name ="ciutat")
//@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"nom", "latitud", "longitud", "superficie", "alcada", "habitants", "patro", "llocsInteres"})
public class Ciutat {

    private String nom;
    private double latitud;
    private double longitud;
    private double superficie;
    private int alcada;
    private int habitants;
    private String patro;
    private final ArrayList<String> llocsInteres = new ArrayList<>();

    
    public Ciutat() {
        
    }
    
    public Ciutat(String nom, double latitud, double longitud, double superficie, int alcada, int 
    habitants, String patro, List<String> llocsInteres) {
        this.nom = nom;
        this.latitud = latitud;
        this.longitud = longitud;
        this.superficie = superficie;
        this.alcada = alcada;
        this.habitants = habitants;
        this.patro = patro;
        this.llocsInteres.addAll(llocsInteres);
    }

    @XmlAttribute
    public String getNom() {
        return nom;
    }

    public void setNom(String nom) {
        this.nom = nom;
    }

    @XmlElement
    public double getLatitud() {
        return latitud;
    }

    public void setLatitud(double latitud) {
        this.latitud = latitud;
    }

    @XmlElement
    public double getLongitud() {
        return longitud;
    }

    public void setLongitud(double longitud) {
        this.longitud = longitud;
    }

    @XmlElement
    public double getSuperficie() {
        return superficie;
    }

    public void setSuperficie(double superficie) {
        this.superficie = superficie;
    }

    @XmlElement
    public int getAlcada() {
        return alcada;
    }

    public void setAlcada(int alcada) {
        this.alcada = alcada;
    }

    @XmlElement
    public int getHabitants() {
        return habitants;
    }

    public void setHabitants(int habitants) {
        this.habitants = habitants;
    }

    @XmlElement
    public String getPatro() {
        return patro;
    }

    public void setPatro(String patro) {
        this.patro = patro;
    }

    @XmlElementWrapper(name = "llocs_interes")
    @XmlElement(name = "lloc_interes")
    public ArrayList<String> getLlocsInteres() {
        return llocsInteres;
    }

    public void setLlocsInteres(List<String> llocsInteres) {
        this.llocsInteres.clear();
        this.llocsInteres.addAll(llocsInteres);
    }

    @Override
    public int hashCode() {
        int hash = 3;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Ciutat other = (Ciutat) obj;
        if (Double.doubleToLongBits(this.latitud) != Double.doubleToLongBits(other.latitud)) {
            return false;
        }
        if (Double.doubleToLongBits(this.longitud) != Double.doubleToLongBits(other.longitud)) {
            return false;
        }
        if (Double.doubleToLongBits(this.superficie) != Double.doubleToLongBits(other.superficie))       
        {
            return false;
        }
        if (this.alcada != other.alcada) {
            return false;
        }
        if (this.habitants != other.habitants) {
            return false;
        }
        if (!Objects.equals(this.nom, other.nom)) {
            return false;
        }
        if (!Objects.equals(this.patro, other.patro)) {
            return false;
        }
        return Objects.equals(this.llocsInteres, other.llocsInteres);
    }
    
    
}`

Manager class (the method is inserir and the error is located in inserir in exprInsert.executeQuery(comandaNom);

`package eac4.gestors;

import eac4.model.Ciutat;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQExpression;


public class GestorCiutat {

    //arrel del document (permet simplificar les expressions)
    public static final String ARREL = "doc(\"ciutats/ciutats.xml\")/collection(\"ciutats\")/";

    private final XQConnection conn;

    public GestorCiutat(XQConnection conn) {
        this.conn = conn;
    }

    public void eliminarTot() throws GestorException {
        try {
            String consulta = "delete node " + ARREL + "ciutats/ciutat";
            XQExpression exp = conn.createExpression();
            exp.executeQuery(consulta);
        } catch (XQException ex) 
        {
            Logger.getLogger(GestorCiutat.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println(ex.getMessage());
            throw new GestorException("Error en esborrar els ciutats", ex);
        }
    }

    public void inserir(Ciutat ciutat) throws GestorException 
    {
        
        try
        {
             
            String comandaNom = "update insert node attribute nom {'" + ciutat.getNom() + "'} into 
            ciutats/ciutat";
            String comandaLatitud = "update insert " + String.valueOf(ciutat.getLatitud()) + " into 
            ciutats/ciutat[@nom[.=" + ciutat.getNom() + "]/latitud";
            String comandaLongitud = "update insert " + String.valueOf(ciutat.getLongitud()) + " 
            into ciutats/ciutat[@nom=" + String.valueOf(ciutat.getNom()) + "]/longitud";
            String comandaSuperficie = "update insert " + String.valueOf(ciutat.getSuperficie()) + 
            " into ciutats/ciutat[@nom=" + String.valueOf(ciutat.getNom()) + "]/superficie";
            String comandaAlcada = "update insert " + String.valueOf(ciutat.getAlcada()) + " into 
            ciutats/ciutat[@nom=" + String.valueOf(ciutat.getNom()) + "]/alcada";
            String comandaHabitants = "update insert " + String.valueOf(ciutat.getHabitants()) + " 
            into ciutats/ciutat[@nom=" + String.valueOf(ciutat.getNom()) + "]/habitants";
            String comandaPatro = "update insert " + ciutat.getPatro()+ " into ciutats/ciutat[nom=" 
            + String.valueOf(ciutat.getNom()) + "]/patro";
        
            
            XQExpression exprInsert = conn.createExpression();
            exprInsert.executeQuery(comandaNom);
            exprInsert.executeQuery(comandaLatitud);
            exprInsert.executeQuery(comandaLongitud);
            exprInsert.executeQuery(comandaSuperficie);
            exprInsert.executeQuery(comandaAlcada);
            exprInsert.executeQuery(comandaHabitants);
            exprInsert.executeQuery(comandaPatro);
            exprInsert.executeQuery("update insert " + ciutat.getLlocsInteres().indexOf(0) + " 
            into ciutats/ciutat[nom=" + String.valueOf(ciutat.getNom()) + "]/llocsinteres/lloc")
            for(int iterPos = 1; iterPos < ciutat.getLlocsInteres().size(); iterPos++)
            {
                exprInsert.executeQuery("update insert lloc/" + 
                ciutat.getLlocsInteres().indexOf(iterPos) + " following ciutats/ciutat[nom=" + 
                String.valueOf(ciutat.getNom()) + "]/llocsinteres/lloc[position=" + iterPos+"]");
            }
        }
        catch(Exception e)
        {
            System.out.println(e.toString());
            e.printStackTrace(System.out);
            throw new GestorException("Error no gestionat al inserir una ciutat!");
        }       
    }

    public void eliminar(String nom) throws GestorException {
        //TODO
        throw new UnsupportedOperationException("Mètode no implementat");
    }

    public Ciutat obtenirCiutat(String nom) throws GestorException {
        //TODO
        throw new UnsupportedOperationException("Mètode no implementat");
    }

    
    public List<Ciutat> obtenirCiutatAmbLlocInteres(String llocInteres) throws GestorException {
        //TODO
        throw new UnsupportedOperationException("Mètode no implementat");
    }

}`

The test (it was giving me many format issues)

https://pastebin.com/z2h4iAtn

The error:

`
 javax.xml.xquery.XQException:
  XQJQS001 - Invalid XQuery syntax, syntax does not pass static validation.
  javax.xml.xquery.XQException:
  XQJQS001 - Invalid XQuery syntax, syntax does not pass static validation.
  Root Cause:
  net.xqj.core.xqparser.v30.ParseException: Encountered " "insert" "insert "" at line 1, column 8.
Was expecting one of:`

Part of stack trace:

 `at net.xqj.core.xqparser.XQueryStatement.compile(XQueryStatement.java:269)
  at net.xqj.core.XQExpression3.executeQuery(XQExpression3.java:89)
  at net.xqj.core.XQExpression3.executeQuery(XQExpression3.java:171)
  at eac4.gestors.GestorCiutat.inserir(GestorCiutat.java:71)
  at eac4.gestors.TestGestors.testInserir(TestGestors.java:155)`

Solution

  • Here it is, XQuery 3.0 and later.

    Tested in BaseX 10.8 beta.

    XQuery

    declare context item := document {
    <root>
      <city>Miami</city>
      <city>Dallas</city>
    </root>
    };
    
    copy $input := .
    modify insert node attribute state {'FL'} into $input/root/city[1]
    return $input
    

    Output

    <root>
      <city state="FL">Miami</city>
      <city>Dallas</city>
    </root>