XPath : select all following siblings until another sibling

前端 未结 3 1152
没有蜡笔的小新
没有蜡笔的小新 2020-11-27 05:54

Here is an excerpt of my xml :



content





        
相关标签:
3条回答
  • 2020-11-27 06:14

    You could do it this way:

    ../node[not(text()) and preceding-sibling::node[@id][1][@id='1']]
    

    where '1' is the id of the current node (generate the expression dynamically).

    The expression says:

    • from the current context go to the parent
    • select those child nodes that
    • have no text and
    • from all "preceding sibling nodes that have an id" the first one must have an id of 1

    If you are in XSLT you can select from the following-sibling axis because you can use the current() function:

    <!-- the for-each is merely to switch the current node -->
    <xsl:for-each select="node[@id='1']">
      <xsl:copy-of select="
        following-sibling::node[
          not(text()) and
          generate-id(preceding-sibling::node[@id][1])
          =
          generate-id(current())
        ]
      " />
    </xsl:for-each>
    

    or simpler (and more efficient) with a key:

    <xsl:key 
      name="kNode" 
      match="node[not(text())]" 
      use="generate-id(preceding-sibling::node[@id][1])"
    />
    
    <xsl:copy-of select="key('kNode', generate-id(node[@id='1']))" />
    
    0 讨论(0)
  • 2020-11-27 06:18

    Simpler than the accepted answer:

    //node[@id='1']/following-sibling::node[following::node[@id='2']]
    
    • Find a node anywhere whose id is '1'
    • Now find all the following sibling node elements
    • ...but only if those elements also have a node with id="2" somewhere after them.

    Shown in action with a more clear test document (and legal id values):

    xml = '<root>
    <node id="a"/><node id="b"/>
    <node id="c">content</node>
    <node id="d"/><node id="e"/><node id="f"/>
    <node id="g">content</node>
    <node id="h"/><node id="i"/>
    </root>'
    
    # A Ruby library that uses libxml2; http://nokogiri.org
    require 'nokogiri'; doc = Nokogiri::XML(xml)
    
    expression = "//node[@id='c']/following-sibling::node[following::node[@id='g']]"
    puts doc.xpath(expression)
    #=> <node id="d"/>
    #=> <node id="e"/>
    #=> <node id="f"/>
    
    0 讨论(0)
  • 2020-11-27 06:34

    XPath 2.0 has the operators '<<' and '>>' where node1 << node2 is true if node1 precedes node2 in document order. So based on that with XPath 2.0 in an XSLT 2.0 stylesheet where the current node is the node[@id = '1'] you could use

      following-sibling::node[not(text()) and . << current()/following-sibling::node[@od][1]]
    

    That also needs the current() function from XSLT, so that is why I said "with XPath 2.0 in an XSLT 2.0 stylesheet". The syntax above is pure XPath, in an XSLT stylesheet you would need to escape '<<' as '&lt;&lt;'.

    0 讨论(0)
提交回复
热议问题