0

What i try to do :

I would like to find the proper xpath to count (or list) links referring to the active node.

my context is javascript with following detached dom tree used to query xpath with document.evaluate giving a specific entry point.

As an example we will consider //*[@id="n11"] as entry point or active node (the second document.evaluate parameter)

here the detached dom tree :

<root>
    <node>
        <a id="n1"/>
        <a id="n2"/>
        <a id="n3"/>
        <a id="n4"/>
        <a id="n5"/>
        <a id="n10"/>
        <a id="n11"/>
        <a id="n12"/>
    </node>
    <link>
        <a><source>n1</source><target>n2</target></a>
        <a><source>n1</source><target>n11</target></a>
        <a><source>n11</source><target>n3</target></a>
        <a><source>n5</source><target>n5</target></a>
    </link>
</root>

I've tried several things but none give me expected result :

  • nodes with no link : /node/*[not(@id = /link/*/source | /link/*/target)]

  • nodes with one link : /node/*[@id = /link/*[not(target = following::source | following::target | preceding::source | preceding::target)]/target] | /node/*[@id = /link/*[not(source = following::source | following::target | preceding::source | preceding::target)]/source]

  • nodes with more than one link /node/*[@id = /link/*[target = following::source | following::target | preceding::source | preceding::target]/target] | /node/*[@id = /link/*[source = following::source | following::target | preceding::source | preceding::target]/source]

but theses dont give me the link number for current node.

this don't work : count(./[@id = /link/*[target | source]])

this not better : count(/link/*[current()/@id = target | source]]) because current exist in xslt context, not xpath only context.

is there an xpath way ?

the 2 other ways i'm thinking are : reworking my dom tree to flatten it more like this :

<root>
    <node id="n1"/>
    <node id="n2"/>
    <node id="n3"/>
    <node id="n4"/>
    <node id="n5"/>
    <node id="n10"/>
    <node id="n11"/>
    <node id="n12"/>
    <link source="n1" target="n2"/>
    <link source="n1" target="n11"/>
    <link source="n11" target="n3"/>
    <link source="n5" target="n5"/>
</root>

but with the first dom tree i can convert any json to dom and query it with xpath, in the second dom tree, i'm more data structure dependent.

The other way i see is to do recursive xpath like this (on first dom tree) : count(/link/*[target | source = {concat('"',@id,'"')}]]) and in javascript looking for nested xpath, evaluate them, replacing them in there parent and evaluating the parent xpath. It could do the trick here, but it will be harder to handle when nested xpath return a node-set and not a string.

Finally, why i'm trying to do this ? for this project : https://github.com/1twitif/social-viz I want to give xpath power to user who want advanced configuration but not giving them the full power of javascript to filter there data to avoid xss in evaluating user untrusted js script.

1000i100
  • 400
  • 1
  • 3
  • 13
  • https://stackoverflow.com/questions/35850586/xpath-1-0-use-the-attribute-value-of-the-current-nodes-parent-to-find-another make me think there is no xpath-1.0 way to do this :/ – 1000i100 Feb 20 '17 at 02:44
  • For the first XML you've provided, to select nodes with no link, does this xpath work? `/root/node/*[not(@id = /root/link/*/*)]` – Lingamurthy CS Feb 20 '17 at 03:42
  • yep like this one : `/node/*[not(@id = /link/*/source | /link/*/target)]` (with /root for xpath explorer, without for document.evaluate). – 1000i100 Feb 21 '17 at 05:55

0 Answers0