Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27266

requiring the value of `xsi:type` to be a type in a specific namespace regardless of prefix

Say I have the following XML file:

<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:foo="http://foo"
   xsi:type="foo:SomeSubtypeOfA">
    boo
</A>

I wish to require that the XML instance is of a specific type derived from A, e.g. type {http://foo}SomeSubtypeOfA (as indeed the above example is). So I am using the following XPath:

/*[@xsi:type='foo:SomeSubtypeOfA']  

... and check whether it succeeds in returning a node or not. However the XPath above is problematic as it relies on the arbitrary prefix so it fails on the following file:

<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:foo2="http://foo"
   xsi:type="foo2:SomeSubtypeOfA">
    boo
</A>

... and it produces a false match on the following file:

<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:foo="http://fooX"
   xsi:type="foo:SomeSubtypeOfA">
    boo
</A>

To get rid of the false match I could write the XPath as:

/*[namespace::foo[.='http://foo'] and @xsi:type='foo:SomeSubtypeOfA'] 

But that still fails to account for the possibility of some other prefix bound to the http://foo namespace. How can I write the above XPath so it checks the namespace of the type given in the xsi:type attribute rather than its prefix?

Upvotes: 2

Views: 786

Answers (1)

Michael Kay
Michael Kay

Reputation: 163262

In XPath 2.0 you can do

/*[namespace-uri-from-QName(resolve-QName(@xsi:type, .)) = 'http://foo' and local-name-from-QName(resolve-QName(@xsi:type, .)) = 'SomeSubtypeOfA']

In XPath 1.0 you need to do something like

//*[namespace::*[name()=substring-before(../@xsi:type, ':')] = 'http://foo/']

(but that probably doesn't allow for the type being in the default namespace)

Upvotes: 3

Related Questions