Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XPath选择节点直到满足条件_Xml_Xpath - Fatal编程技术网

Xml XPath选择节点直到满足条件

Xml XPath选择节点直到满足条件,xml,xpath,Xml,Xpath,我有一个类似于下面的HTML/XML文档。在以任意重复模式切换到另一种颜色之前,可以有一个或多个相同颜色的“tr”。这是一个例子: <tr class='red'></tr> <tr class='blue'></tr> <tr class='red'></tr> <tr class='red'></tr> <tr class='red'></tr> <tr class=

我有一个类似于下面的HTML/XML文档。在以任意重复模式切换到另一种颜色之前,可以有一个或多个相同颜色的“tr”。这是一个例子:

<tr class='red'></tr>
<tr class='blue'></tr>
<tr class='red'></tr>
<tr class='red'></tr>
<tr class='red'></tr>
<tr class='blue'></tr>
<tr class='blue'></tr>
<tr class='red'></tr>
<tr class='red'></tr>
<tr class='blue'></tr>
但这也会选择后续块的第二个+tr。我觉得我已经接近我所需要的了,但是我不能完全做到

提前谢谢


编辑:所需的输出是一个节点集,其中包含块内的后续“tr”,并且仅包含该块。

如果您将变量$v绑定到起始节点,则我认为可以使用如下可怕的低效率来完成:

$v/following-sibling::tr[@class = $v/@class and count(preceding-sibling::tr[not(@class=$v/@class)] = count($v/preceding-sibling::tr[not(@class=$v/@class)])]
如果您的API没有给您绑定变量的机会,那么我认为这是不可能的,尽管我愿意被证明是错误的

您还没有说明约束是什么,但是XPath 1.0似乎不是解决这个特定问题的好技术选择

即使在XPath2.0中,它也不是特别好。您确实需要递归,这意味着使用XQuery或XSLT而不是纯XPath

此XPath 1.0表达式选择蓝色tr元素的第一块:

说明:

对于节点集交点,使用众所周知的Kayessian公式:

此XPath表达式精确选择属于节点集$ns1和节点集$ns2的节点

在这种特殊情况下,我们只需用相应的特定XPath表达式替换$ns1和$ns2——一个是第一个蓝色tr及其所有后续同级,另一个是第一个蓝色tr及其所有之前同级之后的第一个非蓝色tr。这两个节点集的交集正是所需的第一块蓝色trs

基于XSLT的验证:

将此转换应用于以下XML文档时:

计算XPath表达式并将选定节点复制到输出:


我有点困惑。。。您也可以发布所需的输出吗?例如,如果我的起点是红色的第三个'tr',我将只选择第四个和第五个'tr'。不幸的是,我无法绑定变量。限制条件是我只能使用XPath1.0,但由于数据集较小,效率低下不是问题。谢谢你抽出时间回答:谢谢你的回答。然而,我正在寻找一个通用的XPath来选择任何块,使用它作为起点。我理解集合交集的概念,我试图自己重写表达式,但我无法让它工作。如果您有时间,我希望您能提供一个通用的解决方案:@user1300244:这个答案完全解决了问题中当前描述的问题。如果您有其他要求,请编辑问题并准确指定希望XPath选择的节点。对不起,我不同意。问题是我要寻找的是一个XPath 1.0表达式,它从任何颜色“块”中的第一个“tr”开始,仅在该块中选择以下后续的“tr”。@user1300244:这一点定义都不清楚。任何区块的含义是什么?如果希望XPath表达式选择所需的节点,则需要准确地指定该值。例如,我的答案中的表达式显示了如何为第一个蓝色块选择想要的节点。您需要说明哪个块-如果不使用变量引用,您通常无法指定任何块。表达敬意。省去了我很多麻烦
$v/following-sibling::tr[@class = $v/@class and count(preceding-sibling::tr[not(@class=$v/@class)] = count($v/preceding-sibling::tr[not(@class=$v/@class)])]
      (/*/tr[@class='blue'][1] | /*/tr[@class='blue'][1]/following-sibling::tr)
        [count(. | /*/tr[@class='blue'][1]
                          /following-sibling::tr
                                    [not(@class='blue')][1]
                                       /preceding-sibling::*
               )
        =
         count(/*/tr[@class='blue'][1]
                          /following-sibling::tr
                                    [not(@class='blue')][1]
                                       /preceding-sibling::*
         )
         ]
$ns1[count(.|$ns2) = count($ns2)]
<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()|@*">
  <xsl:copy-of select=
  "(/*/tr[@class='blue'][1] | /*/tr[@class='blue'][1]/following-sibling::tr)
            [count(. | /*/tr[@class='blue'][1]
                              /following-sibling::tr
                                        [not(@class='blue')][1]
                                           /preceding-sibling::*
                   )
            =
             count(/*/tr[@class='blue'][1]
                              /following-sibling::tr
                                        [not(@class='blue')][1]
                                           /preceding-sibling::*
                 )
             ]
  "/>
 </xsl:template>
</xsl:stylesheet>
<t>
    <tr class='red'></tr>
    <tr class='red'></tr>
    <tr class='red'></tr>
    <tr class='red'></tr>
    <tr class='blue'></tr>
    <tr class='blue'></tr>
    <tr class='red'></tr>
    <tr class='red'></tr>
    <tr class='blue'></tr>
</t>
<tr class="blue"/>
<tr class="blue"/>