1

I need to create a query on a JAXB generated object using JXPath. The trial code below generates the following error: Exception in thread "main" org.apache.commons.jxpath.JXPathNotFoundException: No value for xpath: //p:OrderDetail

Purchase.xml

<?xml version="1.0"?>
<!-- Created with Liquid XML Studio 0.9.8.0 (http://www.liquid-technologies.com) -->
<p:Purchase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://NamespaceTest.com/Purchase Main.xsd" 
            xmlns:p="http://NamespaceTest.com/Purchase"
            xmlns:o="http://NamespaceTest.com/OrderTypes"
            xmlns:c="http://NamespaceTest.com/CustomerTypes"
            xmlns:cmn="http://NamespaceTest.com/CommonTypes">
<p:OrderDetail>
 <o:Item>
   <o:ProductName>Widget</o:ProductName>
   <o:Quantity>1</o:Quantity>
   <o:UnitPrice>3.42</o:UnitPrice>
  </o:Item>
 </p:OrderDetail>
 <p:PaymentMethod>VISA</p:PaymentMethod>
 <p:CustomerDetails>
  <c:Name>James</c:Name>
  <c:DeliveryAddress>
   <cmn:Line1>15 Some Road</cmn:Line1>
   <cmn:Line2>SomeTown</cmn:Line2>
  </c:DeliveryAddress>
  <c:BillingAddress>
   <cmn:Line1>15 Some Road</cmn:Line1>
   <cmn:Line2>SomeTown</cmn:Line2>
  </c:BillingAddress>
 </p:CustomerDetails>
</p:Purchase>

trial...

JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class);
Unmarshaller um = ctx.createUnmarshaller();
Purchase purchase = (Purchase) um.unmarshal(new File("Purchase.xml"));  

JXPathContext jctx = JXPathContext.newContext(purchase);
jctx.registerNamespace("p", "http://NamespaceTest.com/OrderTypes");
OrderType cust = (OrderType) jctx.getValue("//p:OrderDetail");
System.out.println(cust.getItem());

Purchase.java

    @XmlRootElement(name = "Purchase")
    public class Purchase {

    @XmlElement(name = "OrderDetail", required = true)
    protected OrderType orderDetail;

    /**
 * Gets the value of the orderDetail property.
 * 
 * @return
 *     possible object is
 *     {@link OrderType }
 *     
 */
public OrderType getOrderDetail() {
    return orderDetail;
}

The xml file was taken from: http://www.liquid-technologies.com/Tutorials/XmlSchemas/XsdTutorial_04.aspx

Any ideas that would point me in the right direction to fix this would be apreacitaed?

UESer
  • 25
  • 4
  • Have your `Purchase` object unmarshalled correctly? Does it contain the XML data? Also, are you sure that the results for you `CustomerDetails` query are supposed to be returned as a `OrderType` object (if so, post the relevant parts of your object tree)? If the answer for all of the above is yes, try `List CustomerDetails = ctx.selectNodes("p:CustomerDetails");` – Anthony Accioly Dec 03 '13 at 21:53
  • Would jxpath be aware of the namespaces since you're running jxpath against the unmarshalled object structure? – Taylor Dec 03 '13 at 21:59
  • @AnthonyAccioly looks like my Purchase object unmarshalled correctly as I can call it directly with a result. However, I get an empty array by calling: List jlist = (List) jctx.selectNodes("//p:OrderDetail"); as you suggested. Still stuck. Really appreacite your help Anthony. – UESer Dec 03 '13 at 22:37
  • @UESer I'm pretty sure that your `Purchase` contains a list of order details. So you don't need the inefficient `//` at all (it can be replaced with `/nameOfYourOrderDetailList`. If you can post the relevant parts of your Purchase object, including the getter for your order details list we may be able to further assist you. – Anthony Accioly Dec 03 '13 at 23:00
  • @AnthonyAccioly The Purchase.getOrderDetail() method returns a OrderType object. Good point about the "/", but I have tried multiple xpath query in vain. Let me know if you need more details. The detail of the xml/xsd files can be found here if that can be of any help: http://www.liquid-technologies.com/Tutorials/XmlSchemas/XsdTutorial_04.aspx. – UESer Dec 03 '13 at 23:19
  • I need the object definition (your java file for `Purchase`) – Anthony Accioly Dec 03 '13 at 23:22
  • Also take a look at http://stackoverflow.com/questions/7493412/issue-with-xml-parsing-using-commons-jxpath – Anthony Accioly Dec 03 '13 at 23:24

1 Answers1

0

Since you are constructing a JXPathContext out of a unmarshalled object tree (as opposed to constructing it directly from a xml Document or Element) you should not worry about namespaces.

JXPathContext context = JXPathContext.newContext(purchase);
OrderType orderDetail = (OrderType) context.getValue("orderDetail");
// equivalent to purchase.getOrderDetail()

for(Iterator iter = context.iterate("/orderDetail/items"); iter.hasNext()){
   Item i = (Item) iter.next();
   //...
}
// Assumes that OrderType has a items property
// List<Item> getItems()
Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118