JAXB bindings file: namespace-aware node selection

2019-05-09 21:46发布

I tend to use external JAXB bindings files for my Schema-to-Java compilation. This works just fine, but I did notice one thing that I've started wondering about. It's not really JAXB-specific, more like an XPath question, but the context helps.

Suppose we have this schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:test="www.acme.com"
 targetNamespace="www.acme.com"
 elementFormDefault="qualified" attributeFormDefault="unqualified">

  <xs:element name="el1"/>

  <xs:complexType name="testType">
    <xs:sequence>
      <xs:element ref="test:el1"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>

The element reference in the complex type requires the prefix "test", bound to our target namespace, to find the element definition. If we omitted the prefix, a schema processor would complain that it can't find the element it refers. So obviously the reference is a qualified name and a schema processor is aware of this.

Now take the following bindings file extract for XJC:

<bindings node="//xs:complexType[@name='testType']">
  <bindings node=".//xs:element[@ref='test:el1']">
    <property name="element1"/>
  </bindings>
</bindings>

The binding for the complex type is clear. We select it by name, and the xs prefix is bound in the bindings file's root (not shown here). It might as well be xsd.
What bugs me is the nested binding. In the context of our complex type node, we select an xs:element node for which attribute ref has value test:el1. But that value is simply regarded as text. The XML processor has no knowledge of the fact that it's supposed to be a qualified name and test: is actually a prefix declaration bound to a namespace.

Now I know I'm nitpicking, but the actual prefix string should have no importance, only the namespace URI itself. Someone could change the test prefix in the schema to acme and it would still be the same schema semantically. However, my bindings file would no longer work.

So, is there any way to construct the XPath expression without relying on knowledge of the prefix, only the namespace URI? It's obviously not a big problem, but I'm curious about this.

1条回答
对你真心纯属浪费
2楼-- · 2019-05-09 22:18

Is there any way to construct the XPath expression without relying on knowledge of the prefix, only the namespace URI?

If you talk about an attribute value, this is XPath 1.0

.//xs:element[
   namespace::*[
      . = 'www.acme.com'
   ][
      susbtring-before(
         ../@ref,
         ':'
      )
    = name()
   ]
 and
   substring(
      concat(':', @ref),
      string-length(@ref) - 1
   )
 = 'el1'
]

In XPath 2.0 is much more simple:

.//xs:element[resolve-QName(@ref,.) eq QName('www.acme.com','el1')]
查看更多
登录 后发表回答