Reputation: 24930
Given a relatively simple snippet like:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<h1>Irrelevant</h1>
<item>
<div>
something
<p>Not a target</p>
</div>
</item>
<item>
<h1>Relevant.</h1>
<div>
Location of relevant content
<p>The target.</p>
</div>
</item>
</doc>
I'm interested in finding the path to the target node. I can do this, for example:
//div[contains(.,"content")]/p/path()
The output is:
/Q{}doc[1]/Q{}item[2]/Q{}div[1]/Q{}p[1]
While it's probably helpful in other cases, in this particular case, the inclusion of the namespace uri of the target node name is not very informative.
I know I can forcibly strip Q{uri}
by using replace()
:
replace(//div[contains(.,"content")]/p/path(),"Q\{}","")
which outputs the path I want to see:
/doc[1]/item[2]/div[1]/p[1]
But it becomes cumbersome with multiple expressions.
Is there a way to suppress the inclusion of the namespace uri and receive only the local part of the node name? Absent that, is there another way/function (any version of xpath/xquery) to achieve the same result?
Upvotes: 1
Views: 112
Reputation: 167571
To roll your own function, in this example ignoring the namespaces, for instance, contrast
declare function local:step($node as node()) as xs:string {
typeswitch($node)
case element() return local-name($node) || '[' || (1 + count($node/preceding-sibling::*[node-name() = node-name($node)])) || ']'
case text() return 'text()' || '[' || (1 + count($node/preceding-sibling::text())) || ']'
case comment() return 'comment()' || '[' || (1 + count($node/preceding-sibling::comment())) || ']'
case processing-instruction() return 'processing-instruction(' || node-name($node) || ')' || '[' || (1 + count($node/preceding-sibling::processing-instruction()[node-name() = node-name($node)]))|| ']'
default return ''
};
declare function local:path($node as node()) as xs:string {
string-join($node/ancestor-or-self::node()!local:step(.), '/')
};
//div[contains(.,"content")]/p/(path(), local:path(.))
https://xqueryfiddle.liberty-development.net/bdxZ8T
Upvotes: 2