Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selecting nodes with XPath for binding a subset of classes with JAXB

Tags:

xml

jaxb

xpath

xsd

xjc

Simplified Question: What's the XPath to select all XML nodes with an attribute that ends with the string "Notification". The first and third nodes in this snippet:

 <events>
   <event name="CreatedNotification" />
   <event name="InfoLog" />
   <event name="UpdatedNotification" />
 </events>

Detailed Question:

I want to select multiple complexTypes from a xsd schema for binding with JAXB. This works for a single class: OrderStateChangeNotification

<jxb:bindings schemaLocation="apiv2.xsd">
  <jxb:bindings node="//xs:complexType[@name='OrderStateChangeNotification']">
    <inheritance:implements>com.google.checkout.sdk.notifications.Notification</inheritance:implements> 
  </jxb:bindings>
</jxb:bindings>

Here is the relevant snippet from the schema schema file:

  <xs:complexType name="OrderStateChangeNotification">
    <xs:all>
      <xs:element name="new-fulfillment-order-state" type="tns:FulfillmentOrderState" />
      <xs:element name="new-financial-order-state" type="tns:FinancialOrderState" />
      <xs:element name="previous-fulfillment-order-state" type="tns:FulfillmentOrderState" />
      <xs:element name="previous-financial-order-state" type="tns:FinancialOrderState" />
      <xs:element name="reason" type="xs:string" minOccurs="0" />
      <xs:element name="timestamp" type="xs:dateTime" />
      <xs:element name="google-order-number" type="xs:token" />
      <xs:element name="order-summary" type="tns:OrderSummary" minOccurs="0" />
    </xs:all>
    <xs:attribute name="serial-number" type="xs:string" use="required" />
  </xs:complexType>

  <xs:complexType name="ChargeAmountNotification">
    <xs:all>
      <xs:element name="timestamp" type="xs:dateTime" />
      <xs:element name="latest-charge-amount" type="tns:Money" />
      <xs:element name="latest-charge-fee" type="tns:FeeStructure" minOccurs="0" />
      <xs:element name="total-charge-amount" type="tns:Money" />
      <xs:element name="latest-promotion-charge-amount" type="tns:Money" minOccurs="0" />
      <xs:element name="google-order-number" type="xs:token" />
      <xs:element name="order-summary" type="tns:OrderSummary" minOccurs="0" />
    </xs:all>
    <xs:attribute name="serial-number" type="xs:string" use="required" />
  </xs:complexType>

I want the binding to apply to all notification objects. They all end in with "Notification"

I've tried changing the XPath from

//xs:complexType[@name='OrderStateChangeNotification']

to

//xs:complexType[substring(name(), string-length(name()) - 12) = 'Notification']

but it didn't work.

Another approach is to try and select all nodes with the children "order-summary" and "serial-number" as I know only Notification objects have these.

UPDATE: The solution by @Lee Greco correctly selectes the nodes I wanted, but unfortunatly, the inheritance plugin is not compatible with multiple nodes:

[ERROR] XPath evaluation of "//xs:complexType[substring(@name, string-length(@name)-string-length('Notification')+1)='Notification']" results in too many (8) target nodes

I ended up just enumerating them separately.

like image 910
matt burns Avatar asked Feb 10 '12 16:02

matt burns


People also ask

What is JAXB binding file?

JAXB is an XML-to-Java binding technology that enables transformation between schema and Java objects and between XML instance documents and Java object instances. JAXB technology consists of a runtime API and accompanying tools that simplify access to XML documents.

What is XPath selector?

XPath stands for XML Path Language. It uses a non-XML syntax to provide a flexible way of addressing (pointing to) different parts of an XML document. It can also be used to test addressed nodes within a document to determine whether they match a pattern or not.

What is XPath expression in XML?

XPath is a syntax for defining parts of an XML document. XPath uses path expressions to navigate in XML documents. XPath contains a library of standard functions. XPath is a major element in XSLT and in XQuery. XPath is a W3C recommendation.

What is the use of XJB file?

Generally we create a bindings file with . xjb extension to resolve any conflicts in the WSDL or schema. For example if two elements have the same name and you want to distinguish between them you can rename one by specifying it the bindings file.


1 Answers

I had the same problem. I found out there was a multiple attribute that was used by XJC to allow multiple node match.

I also wanted the binding to apply to every schema locations. xs:anyURI did not work but I found a way to do it using the * token. I added the required="false" attribute in order to ignore schemas that does not contain any match.

<jxb:bindings schemaLocation="*">
  <jxb:bindings node="//xs:complexType[substring(name(), string-length(name()) - 12) = 'Notification']" multiple="true" required="false">
    <inheritance:implements>com.google.checkout.sdk.notifications.Notification</inheritance:implements> 
  </jxb:bindings>
</jxb:bindings>

Edit: I posted this answer without reading the comments of the question. Sorry for that. I'm using maven plugin org.codehaus.mojo:jaxb2-maven-plugin:1.5 with XJC plugin org.jvnet.jaxb2_commons:jaxb2-basics-project:0.6.4 and it seems to work like this...

like image 105
boumbh Avatar answered Sep 21 '22 08:09

boumbh