简体   繁体   中英

Is there a way to change the return value of fn:path()?

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM