Выбор узлов с XPath для привязки подмножества классов с JAXB
Упрощенный вопрос:
Что XPath выбрать все узлы XML с атрибутом, который заканчивается строкой "Уведомление". Первый и третий узлы в этом фрагменте:
<events>
<event name="CreatedNotification" />
<event name="InfoLog" />
<event name="UpdatedNotification" />
</events>
Подробный вопрос:
Я хочу выбрать несколько complexTypes из схемы xsd для привязки к JAXB. Это работает для одного класса: 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>
Вот соответствующий фрагмент из файла схемы схемы:
<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>
Я хочу, чтобы привязка применялась ко всем объектам уведомлений. Все они заканчиваются словами "Уведомление"
Я попытался изменить XPath из
//xs:complexType[@name='OrderStateChangeNotification']
к
//xs:complexType[substring(name(), string-length(name()) - 12) = 'Notification']
но это не сработало.
Другой подход состоит в том, чтобы попытаться выбрать все узлы с дочерними словами "order-summary" и "serial-number", как я знаю, только эти объекты уведомлений имеют.
UPDATE:
Решение @Lee Greco правильно выбирает узлы, которые я хотел, но, к сожалению, плагин наследования несовместим с несколькими узлами:
[ERROR] XPath evaluation of "//xs:complexType[substring(@name, string-length(@name)-string-length('Notification')+1)='Notification']" results in too many (8) target nodes
В итоге я просто перечислил их отдельно.
Ответы
Ответ 1
С помощью
//xs:complexType[substring(name(), string-length(name()) - 12) = 'Notification']
выражение, которое вы запрашиваете для всех элементов, где имя элемента заканчивается в "Уведомлении". Вы действительно хотите спросить все элементы с атрибутом имени, который заканчивается в "Уведомлении".
Попробуйте это вместо:
//xs:complexType[substring(@name, string-length(@name)-string-length("Notification")+1)="Notification"]
Ответ 2
У меня была та же проблема. Я узнал, что существует атрибут multiple
, который использовался XJC, чтобы разрешить несколько node.
Я также хотел, чтобы привязка применялась к каждому местоположению схемы. xs:anyURI
не работал, но я нашел способ сделать это, используя токен *
. Я добавил атрибут required="false"
, чтобы игнорировать схемы, которые не содержат соответствия.
<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>
Изменить: Я опубликовал этот ответ, не прочитав комментарии к вопросу. Простите за это. Я использую плагин maven org.codehaus.mojo:jaxb2-maven-plugin:1.5
с плагином XJC org.jvnet.jaxb2_commons:jaxb2-basics-project:0.6.4
и, похоже, работает так...
Ответ 3
В итоге у меня возникла аналогичная проблема "слишком много целевых узлов (3)", однако не удалось найти ответа ни на одном из сайтов... Опубликовать решение, которое я нашел после многих проб и ошибок... Основная идея для решения "слишком много целевых узлов (3)" заключается в том, чтобы дать полный XPATH node, который кратен вашему XSD.
Ниже мой XSD:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="document">
<xs:complexType>
<xs:sequence>
<xs:element name="asset">
<xs:complexType>
<xs:sequence>
<xs:element name="attribute" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="string" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="value" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="date" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="value" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="array" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="struct" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="field" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="integer" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:byte" name="value"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="assetreference" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="type"/>
<xs:attribute type="xs:long" name="value"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="integer" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:long" name="value"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="file" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="name" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="integer" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="value"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:long" name="id"/>
<xs:attribute type="xs:string" name="type"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
и ниже - файл привязки JAXB, который работает над XSD:
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.1">
<bindings schemaLocation= "../assetproduct.xsd" version="1.0">
<!-- Customise the package name
<schemaBindings>
<package name="com.example.schema"/>
</schemaBindings> -->
<!-- rename the value element -->
<bindings node="//xs:element[@name='document']">
<bindings node="//xs:element[@name='asset']">
<bindings node="//xs:element[@name='attribute']">
<bindings node="//xs:element[@name='string']">
<bindings node=".//xs:attribute[@name='value']">
<property name="ValueAttribute"/>
</bindings>
</bindings>
<bindings node="//xs:element[@name='date']">
<bindings node=".//xs:attribute[@name='value']">
<property name="ValueAttribute"/>
</bindings>
</bindings>
<bindings node="//xs:element[@name='array']">
<bindings node=".//xs:element[@name='struct']">
<bindings node=".//xs:element[@name='field']">
<bindings node=".//xs:element[@name='integer']/xs:complexType">
<bindings node=".//xs:attribute[@name='value']">
<property name="ValueAttribute"/>
</bindings>
</bindings>
<bindings node=".//xs:element[@name='assetreference']">
<bindings node=".//xs:attribute[@name='value']">
<property name="ValueAttribute"/>
</bindings>
</bindings>
</bindings>
</bindings>
</bindings>
<bindings node=".//xs:element[@name='array']/xs:complexType/xs:sequence/xs:element[@name='integer']">
<bindings node=".//xs:attribute[@name='value']">
<property name="ValueAttribute"/>
</bindings>
</bindings>
<bindings node="//xs:element[@name='attribute']/xs:complexType/xs:sequence/xs:element[@name='integer']">
<bindings node=".//xs:attribute[@name='value']">
<property name="ValueAttribute"/>
</bindings>
</bindings>
</bindings>
</bindings>
</bindings>
</bindings>
</bindings>