2012-02-10 46 views
10

Pregunta simplificada: ¿Qué es XPath para seleccionar todos los nodos XML con un atributo que finaliza con la cadena "Notificación". El primer y tercer nodos en este fragmento:Seleccionar nodos con XPath para vincular un subconjunto de clases con JAXB

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

Pregunta detallada:

deseo seleccionar múltiples complexTypes de un esquema XSD para la unión con JAXB. Esto funciona para una sola clase: 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> 

Aquí está el fragmento relevante desde el archivo de esquema esquema:

<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> 

Quiero que la unión a aplicarse a todos los objetos de notificación. Todos terminan con "notificación"

He intentado cambiar el XPath de

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

a

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

pero no funcionó.

Otro enfoque es tratar de seleccionar todos los nodos con los niños "order-summary" y "serial-number", ya que solo sé que los objetos de notificación los tienen.

ACTUALIZACIÓN: La solución por @Lee Greco SELECTES correctamente los nodos que quería, pero por desgracia, el complemento de la herencia no es compatible con múltiples nodos:

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

Acabé la enumeración de ellos por separado.

+2

Con el fin de apoyar a "múltiples nodos", utilizar el 'múltiple = "verdadero" 'configuración en' '. Ver la [discusión aquí] (http://java.net/projects/jaxb/lists/users/archive/2011-04/message/11) –

+0

La última entrada en la [discusión] (http://java.net/projects/jaxb/lists/users/archive/2011-04/message/11) aún dice que no está funcionando. Tengo el mismo problema y aunque se aceptan multiple = true y required = false, jaxb todavía se ahoga con "XPath evaluation of" // xs: complexType "da como resultado demasiados (3) nodos de destino" .. – whaefelinger

Respuesta

5

Con la expresión

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

que está pidiendo todos los elementos donde el nombre elemento termina en 'Notificación'. Realmente desea solicitar todos los elementos con un atributo de nombre que termine en 'Notificación'.

Tal vez puedas probar:

//xs:complexType[substring(@name, string-length(@name)-string-length("Notification")+1)="Notification"] 
+1

Este XPath es correcto , Gracias. Sin embargo, no funciona en mi contexto porque resulta que mi complemento XJC no puede aceptar consultas XPath que devuelven múltiples nodos. ¡De todas formas, gracias por la ayuda! –

5

que tenían el mismo problema. Descubrí que había un atributo multiple que XJC usaba para permitir la coincidencia de múltiples nodos.

También quería que el enlace se aplicara a cada ubicación de esquema. xs:anyURI no funcionó, pero encontré una forma de hacerlo utilizando el token *. Agregué el atributo required="false" para ignorar los esquemas que no contienen ninguna coincidencia.

<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> 

Editar: he publicado esta respuesta sin necesidad de leer los comentarios de la cuestión. Lo siento por eso.Estoy usando el complemento maven org.codehaus.mojo:jaxb2-maven-plugin:1.5 con el plugin XJC org.jvnet.jaxb2_commons:jaxb2-basics-project:0.6.4 y parece funcionar así ...

0

Terminé con un problema similar "demasiados nodos de destino (3)" sin embargo no pude encontrar ninguna respuesta en ninguno de los sitios ... Publicando la solución que encontré después de muchos rastros y errores ... La idea básica para resolver "demasiados nodos objetivo (3)" es dar XPATH completa del nodo que es múltiple en su XSD.

A continuación es mi 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> 

y por debajo es el archivo de enlace JAXB que está trabajando para arriba 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> 
Cuestiones relacionadas