I generated the Java classes using JAXB an" /> I generated the Java classes using JAXB an" /> I generated the Java classes using JAXB an"/>

Apache JXPath attribute selector not working

33 Views Asked by At

I have this XML:

<workflow>
    <initial-actions>
        <action id="1" name="Create"/>
    </initial-actions>
</workflow>

I generated the Java classes using JAXB and successfully unmarshalled it in variable "wf".

Then invoking JXPath:

String xpath = "initialActions/action[@name='Create']";
JXPathContext context = JXPathContext.newContext(wf);
Object v = context.getValue(xpath);

JXPath would complain that no value is found. But if I change the selector to id:

String xpath = "initialActions/action[@id='1']/@name";
JXPathContext context = JXPathContext.newContext(wf);
Object v = context.getValue(xpath);

Then v contains "Create".

Why @name selector finds nothing?

Edit: This is the Action class generated by JAXB:

/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType&gt;
 *   &lt;complexContent&gt;
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
 *       &lt;sequence&gt;
 *         &lt;element ref="{}meta" maxOccurs="unbounded" minOccurs="0"/&gt;
 *         &lt;element ref="{}restrict-to" minOccurs="0"/&gt;
 *         &lt;element ref="{}validators" minOccurs="0"/&gt;
 *         &lt;element ref="{}pre-functions" minOccurs="0"/&gt;
 *         &lt;element ref="{}results"/&gt;
 *         &lt;element ref="{}post-functions" minOccurs="0"/&gt;
 *       &lt;/sequence&gt;
 *       &lt;attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /&gt;
 *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /&gt;
 *       &lt;attribute name="view" type="{http://www.w3.org/2001/XMLSchema}string" /&gt;
 *       &lt;attribute name="auto"&gt;
 *         &lt;simpleType&gt;
 *           &lt;restriction base="{http://www.w3.org/2001/XMLSchema}NMTOKEN"&gt;
 *             &lt;enumeration value="TRUE"/&gt;
 *             &lt;enumeration value="FALSE"/&gt;
 *             &lt;enumeration value="true"/&gt;
 *             &lt;enumeration value="false"/&gt;
 *           &lt;/restriction&gt;
 *         &lt;/simpleType&gt;
 *       &lt;/attribute&gt;
 *       &lt;attribute name="finish"&gt;
 *         &lt;simpleType&gt;
 *           &lt;restriction base="{http://www.w3.org/2001/XMLSchema}NMTOKEN"&gt;
 *             &lt;enumeration value="TRUE"/&gt;
 *             &lt;enumeration value="FALSE"/&gt;
 *             &lt;enumeration value="true"/&gt;
 *             &lt;enumeration value="false"/&gt;
 *           &lt;/restriction&gt;
 *         &lt;/simpleType&gt;
 *       &lt;/attribute&gt;
 *     &lt;/restriction&gt;
 *   &lt;/complexContent&gt;
 * &lt;/complexType&gt;
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "meta",
    "restrictTo",
    "validators",
    "preFunctions",
    "results",
    "postFunctions"
})
@XmlRootElement(name = "action")
public class Action
    implements WorkflowPart
{

    protected List<Meta> meta;
    @XmlElement(name = "restrict-to")
    protected RestrictTo restrictTo;
    protected Validators validators;
    @XmlElement(name = "pre-functions")
    protected PreFunctions preFunctions;
    @XmlElement(required = true)
    protected Results results;
    @XmlElement(name = "post-functions")
    protected PostFunctions postFunctions;
    @XmlAttribute(name = "id", required = true)
    protected String id;
    @XmlAttribute(name = "name", required = true)
    protected String name;
    @XmlAttribute(name = "view")
    protected String view;
    @XmlAttribute(name = "auto")
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    protected String auto;
    @XmlAttribute(name = "finish")
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    protected String finish;

    /**
     * Gets the value of the meta property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the meta property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getMeta().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link Meta }
     * 
     * 
     */
    public List<Meta> getMeta() {
        if (meta == null) {
            meta = new ArrayList<Meta>();
        }
        return this.meta;
    }

    /**
     * Gets the value of the restrictTo property.
     * 
     * @return
     *     possible object is
     *     {@link RestrictTo }
     *     
     */
    public RestrictTo getRestrictTo() {
        return restrictTo;
    }

    /**
     * Sets the value of the restrictTo property.
     * 
     * @param value
     *     allowed object is
     *     {@link RestrictTo }
     *     
     */
    public void setRestrictTo(RestrictTo value) {
        this.restrictTo = value;
    }

    /**
     * Gets the value of the validators property.
     * 
     * @return
     *     possible object is
     *     {@link Validators }
     *     
     */
    public Validators getValidators() {
        return validators;
    }

    /**
     * Sets the value of the validators property.
     * 
     * @param value
     *     allowed object is
     *     {@link Validators }
     *     
     */
    public void setValidators(Validators value) {
        this.validators = value;
    }

    /**
     * Gets the value of the preFunctions property.
     * 
     * @return
     *     possible object is
     *     {@link PreFunctions }
     *     
     */
    public PreFunctions getPreFunctions() {
        return preFunctions;
    }

    /**
     * Sets the value of the preFunctions property.
     * 
     * @param value
     *     allowed object is
     *     {@link PreFunctions }
     *     
     */
    public void setPreFunctions(PreFunctions value) {
        this.preFunctions = value;
    }

    /**
     * Gets the value of the results property.
     * 
     * @return
     *     possible object is
     *     {@link Results }
     *     
     */
    public Results getResults() {
        return results;
    }

    /**
     * Sets the value of the results property.
     * 
     * @param value
     *     allowed object is
     *     {@link Results }
     *     
     */
    public void setResults(Results value) {
        this.results = value;
    }

    /**
     * Gets the value of the postFunctions property.
     * 
     * @return
     *     possible object is
     *     {@link PostFunctions }
     *     
     */
    public PostFunctions getPostFunctions() {
        return postFunctions;
    }

    /**
     * Sets the value of the postFunctions property.
     * 
     * @param value
     *     allowed object is
     *     {@link PostFunctions }
     *     
     */
    public void setPostFunctions(PostFunctions value) {
        this.postFunctions = value;
    }

    /**
     * Gets the value of the id property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getId() {
        return id;
    }

    /**
     * Sets the value of the id property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setId(String value) {
        this.id = value;
    }

    /**
     * Gets the value of the name property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the value of the name property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setName(String value) {
        this.name = value;
    }

    /**
     * Gets the value of the view property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getView() {
        return view;
    }

    /**
     * Sets the value of the view property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setView(String value) {
        this.view = value;
    }

    /**
     * Gets the value of the auto property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getAuto() {
        return auto;
    }

    /**
     * Sets the value of the auto property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setAuto(String value) {
        this.auto = value;
    }

    /**
     * Gets the value of the finish property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getFinish() {
        return finish;
    }

    /**
     * Sets the value of the finish property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setFinish(String value) {
        this.finish = value;
    }

}

Edit 2: This XPath works (remove @ in front of name):

String xpath = "initialActions/action[name='Create']";

And these two produce the same value:

String xpath = "initialActions/action[name='Create']/@name";
String xpath2 = "initialActions/action[name='Create']/name";

While name is an attribute in the XML, in the JAXB generated class it is just a normal field.

JXPath documentation says,

For JavaBeans and Maps the "attribute::" axis is interpreted the same as the "child::" axis.

which explains why both @name and name work to retrieve the value.

But then when would you use @attributeName in JXPath? Is it only needed if you use XMLDocumentContainer?

0

There are 0 best solutions below