XSLT-选择在另一个节点之后的节点

我正在尝试选择1)具有特定属性的节点和2)具有特定属性的所有节点。因此,如果我具有以下XML:
<node id=\"1\"><child attr=\"valueOfInterest\"/></node>
<node id=\"2\"><child attr=\"boringValue\"/></node>
...
<node id=\"3\"><child attr=\"valueOfInterest\"/></node>
<node id=\"4\"><child attr=\"boringValue\"/></node>
<node id=\"5\"><child attr=\"boringValue\"/></node>
<node id=\"6\"><child attr=\"boringValue\"/></node>
...
我的XSLT遍历每个
node
标记。在每个ѭ1上,我希望它选择从最近的
node
中出现的所有
node
,其中最近的
node
具有
child
,而
attr
valueOfInterest
。因此,如果我在节点2上,则需要一个空节点集。如果我在节点#6上,我想选择节点#\的4和5。我目前有以下XSLT:
<xsl:variable name=\"prev_vals\"
    select=\"preceding-sibling::node/child[@attr = $someValueICareAbout]/@attr\"/>
因此,此XSLT获得所有前面的特定值
attr
值。我该如何只获得那些在ѭ1preceding中位于
node
之后的值,这些值在最近的ѭ1after之后,而其最近的ѭ5中具有特定的
attr
值(即\“ valueOfInterest \”)?不能保证
node
标签上的
id
属性会增加,因此我们无法与之相比。 编辑:我认为这些可能是有用的:
<xsl:variable name=\"prev_children_of_interest\"
    select=\"preceding-sibling::node/child[@attr != $someValueICareAbout]\"/>
<xsl:variable name=\"mru_child_of_interest\"
    select=\"$prev_children_of_interest[count($prev_children_of_interest)]\"/>
因此,这是所有带有ѭ19的
child
标记,然后是具有我正在寻找的属性的最近使用的(最接近当前节点的)
child
标记。从
mru_child_of_interest
,我们可以找到最近使用的
parent
标签,但是我们如何查找该标签之后的节点?     
已邀请:
        我不确定我是否正确理解了您的问题,但这是一些XSL 1.0(附加的
each-nodes
属性仅供参考):
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">
    <xsl:output method=\"xml\" indent=\"yes\"/>

    <xsl:template match=\"nodes\">
        <xsl:copy>
            <xsl:apply-templates select=\"node\"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match=\"node\">
        <xsl:variable name=\"someValueICareAbout\">valueOfInterest</xsl:variable>

        <xsl:variable name=\"recentParticularNode\"
            select=\"preceding-sibling::node[child/@attr = $someValueICareAbout][1]\"/>

        <xsl:variable name=\"recentParticularNodePosition\"
            select=\"count($recentParticularNode/preceding-sibling::node) + 1\"/>

        <xsl:variable name=\"currentPosition\" select=\"position()\"/>

        <xsl:if test=\"child/@attr != $someValueICareAbout\">
            <each-nodes id=\"{@id}\" cp=\"{$currentPosition}\" 
                    rpnp=\"{$recentParticularNodePosition}\">
                <xsl:copy-of
                    select=\"../node[position() &gt; $recentParticularNodePosition
                    and position() &lt; $currentPosition]\"/>
            </each-nodes>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
输入XML:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<nodes>
    <node id=\"1\"><child attr=\"valueOfInterest\"/></node>
    <node id=\"2\"><child attr=\"boringValue2\"/></node>
    <node id=\"3\"><child attr=\"valueOfInterest\"/></node>
    <node id=\"4\"><child attr=\"boringValue4\"/></node>
    <node id=\"5\"><child attr=\"boringValue5\"/></node>
    <node id=\"6\"><child attr=\"boringValue6\"/></node>
</nodes>
结果XML:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<nodes>
   <each-nodes id=\"2\" cp=\"2\" rpnp=\"1\"/>
   <each-nodes id=\"4\" cp=\"4\" rpnp=\"3\"/>
   <each-nodes id=\"5\" cp=\"5\" rpnp=\"3\">
      <node id=\"4\">
         <child attr=\"boringValue4\"/>
      </node>
   </each-nodes>
   <each-nodes id=\"6\" cp=\"6\" rpnp=\"3\">
      <node id=\"4\">
         <child attr=\"boringValue4\"/>
      </node>
      <node id=\"5\">
         <child attr=\"boringValue5\"/>
      </node>
   </each-nodes>
</nodes>
    
        此转换精确复制所需的节点:
<xsl:stylesheet version=\"1.0\"
 xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">
 <xsl:output omit-xml-declaration=\"yes\" indent=\"yes\"/>
 <xsl:strip-space elements=\"*\"/>

 <xsl:template match=
 \"node[not(child/attr=\'valueOfInterest\')]\">

 <xsl:variable name=\"vFollowing\" select=
 \"preceding-sibling::node
          [child/@attr=\'valueOfInterest\'][1]
            /following-sibling::node\"/>

 <xsl:variable name=\"vPreceding\" select=
  \"preceding-sibling::node\"/>

  <xsl:copy-of select=
  \"$vFollowing[count(. | $vPreceding)
              =
               count($vPreceding)
              ]
  \"/>
======================
 </xsl:template>
 <xsl:template match=\"text()\"/>
</xsl:stylesheet>
应用于此XML文档时(基于提供的XML片段并将其包装在top元素中,以使其成为格式正确的XML文档):
<t>
    <node id=\"1\">
        <child attr=\"valueOfInterest\"/>
    </node>
    <node id=\"2\">
        <child attr=\"boringValue\"/>
    </node>...
    <node id=\"3\">
        <child attr=\"valueOfInterest\"/>
    </node>
    <node id=\"4\">
        <child attr=\"boringValue\"/>
    </node>
    <node id=\"5\">
        <child attr=\"boringValue\"/>
    </node>
    <node id=\"6\">
        <child attr=\"boringValue\"/>
    </node>...
</t>
所需的正确结果产生了:
======================

======================
 <node id=\"2\">
   <child attr=\"boringValue\"/>
</node>
======================

======================
 <node id=\"4\">
   <child attr=\"boringValue\"/>
</node>
======================
 <node id=\"4\">
   <child attr=\"boringValue\"/>
</node>
<node id=\"5\">
   <child attr=\"boringValue\"/>
</node>
======================
说明: 在这里,我们对两个节点集
$ns1
$ns2
的交集使用著名的Kayessian公式(由SO用户@Michael Kay发现): ns1 [count(。| $ ns2)= count($ ns2)] 在上述公式中,我们仅用
$vFollowing
$vPreceding
代替
$ns1
$ns2
。 满足条件的“ 36节点”到“ 37节点”。 “ 33”是当前(匹配)节点的同级元素中所有“ 1”元素的集合。 .3。它们的交集正是所需的节点集。     
        看起来您想要两个集合的交集。集1是最后一个
valueOfInterest
之后的所有节点。集2是当前节点之前的所有不包含7的节点。对于XPath 1.0,以下内容将为您提供交叉点(在此处找到参考)。
$set1[count($set2|.)=count($set2)]
根据您的输入,以下XSL演示了您要寻找的节点集
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">
  <xsl:output method=\"xml\" indent=\"yes\"/>
  <xsl:strip-space elements=\"*\"/>
  <xsl:variable name=\"someValueICareAbout\">valueOfInterest</xsl:variable>
  <xsl:template match=\"@* | node()\">
    <xsl:copy>
      <xsl:apply-templates select=\"@* | node()\"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match=\"node[child/@attr=\'boringValue\']\">
    <xsl:copy>
      <xsl:apply-templates select=\"@* | node()\"/>

      <xsl:variable name=\"set1\" select=\"preceding-sibling::node[child/@attr=\'valueOfInterest\'][1]/following-sibling::node \"/>

      <xsl:variable name=\"set2\" select=\"preceding-sibling::node[child/@attr=\'boringValue\']\"/>

      <predecessors>
          <xsl:copy-of select=\"$set1[count($set2|.)=count($set2)]\"/>
      </predecessors>

    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
这是输出
<xml>
  <node id=\"1\">
    <child attr=\"valueOfInterest\"/>
  </node>
  <node id=\"2\">
    <child attr=\"boringValue\"/>
    <predecessors/>
  </node>
  <node id=\"3\">
    <child attr=\"valueOfInterest\"/>
  </node>
  <node id=\"4\">
    <child attr=\"boringValue\"/>
    <predecessors/>
  </node>
  <node id=\"5\">
    <child attr=\"boringValue\"/>
    <predecessors>
      <node id=\"4\">
        <child attr=\"boringValue\"/>
      </node>
    </predecessors>
  </node>
  <node id=\"6\">
    <child attr=\"boringValue\"/>
    <predecessors>
      <node id=\"4\">
        <child attr=\"boringValue\"/>
      </node>
      <node id=\"5\">
        <child attr=\"boringValue\"/>
      </node>
    </predecessors>
  </node>
</xml>
注意,我在
preceding-sibling::node[child/@attr=\'valueOfInterest\'][1]
中使用
[1]
的原因是因为节点集的顺序被
preceding-sibling
颠倒了,请参见此处。 如果您具有XPath 2.0,则可以使用
intersect
运算符
  <predecessors>
    <xsl:copy-of select=\"$set1 intersect $set2\"/>
  </predecessors>
这将产生相同的结果。     
        这是在XSLT 2.0中执行此操作的一种方法:
<xsl:variable name=\"prevVOI\"
      select=\"(preceding-sibling::node[child/@attr = \'valueOfInterest\'])[last()]\" />
<xsl:variable name=\"prevNodesAfterVOI\"
      select=\"preceding-sibling::node[. >> $prevVOI]\" />
    

要回复问题请先登录注册