从 XPath 查询中排除节点


exclude nodes from xpath query

这是我目前正在使用的一些代码。我需要帮助的地方是$bn_name_search$bn_id_search

$xpath_base='/ItemSearchResponse/Items/Item[';
for ($i = 1; $i<=10; $i++)
  {
    $curr_item_base=$xpath_base.$i.']';
    $bn_name_search=$curr_item_base.'/BrowseNodes//BrowseNode/Name/text()';
    $bn_id_search=$curr_item_base.'/BrowseNodes//BrowseNode/BrowseNodeId/text()';
    $bn_names=$parsed->xpath($bn_name_search);
    $bn_ids=$parsed->xpath($bn_id_search);
  }

这给了我所有的 browsnode 名称和所有的 broswnode id。我现在想做的是只找到不是"所有产品"的浏览节点名称"BrowseNode/Name/",并且只有眉节点 ID"BrowseNode/BrowseNodeId/"共享一个"BrowseNode/",名称不是"所有产品"我不必测试BrowseNode/Name的存在。如果有 ID,它不会为空。如果我能放两个否定的表达,那就更好了。我会省略那些名称为"所有产品"和名称为"部门"

的人

编辑:这是XML的一个块:在它说" &lt;Name&gt;Departments&lt;/Name&gt;"的地方,我想排除该名称及其ID。如果我有一个类似的说" &lt;Name&gt;All Products&lt;/Name&gt; ",我也想排除该名称及其ID &lt;BrowseNodeId&gt;

<BrowseNodes>
  <BrowseNode>
    <BrowseNodeId>2346727011</BrowseNodeId>
    <Name>Casual</Name>
    <Ancestors>
      <BrowseNode>
        <BrowseNodeId>1045024</BrowseNodeId>
        <Name>Dresses</Name>
        <Ancestors>
          <BrowseNode>
            <BrowseNodeId>1040660</BrowseNodeId>
            <Name>Women</Name>
            <Ancestors>
              <BrowseNode>
                <BrowseNodeId>1036682</BrowseNodeId>
                <Name>Departments</Name>
                <IsCategoryRoot>1</IsCategoryRoot>
                <Ancestors>
                  <BrowseNode>
                    <BrowseNodeId>1036592</BrowseNodeId>
                    <Name>Clothing &amp; Accessories</Name>
                  </BrowseNode>
                </Ancestors>
              </BrowseNode>
            </Ancestors>
          </BrowseNode>
        </Ancestors>
      </BrowseNode>
    </Ancestors>
  </BrowseNode>
</BrowseNodes>

你去吧:

$nodes = $parsed->xpath("//BrowseNode[Name!='Departments' and Name!='All Products']");
foreach ($nodes as $node) {
    echo "Id: {$node->BrowseNodeId}, name: {$node->Name}'n";
}

使用

//BrowseNode
      [not(contains('|Departments|All Products|',
                    concat('|', Name, '|')
                    )
          )
      ]/Name

此表达式选择作为 BrowseNode 元素的子元素且其字符串值不是字符串之一的任何Name元素 "Departments""All Products"

用途

//BrowseNode
      [not(contains('|Departments|All Products|',
                    concat('|', Name, '|')
                    )
          )
      ]
       /BrowseNodeId

这将选择任何BrowseNodeId元素,该元素是BrowseNode元素的子元素,并且具有字符串值不是字符串之一的Name同级元素"Departments""All Products"

基于 XSLT 的验证

<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="/">
  <xsl:copy-of select=
   "//BrowseNode
      [not(contains('|Departments|All Products|',
                    concat('|', Name, '|')
                    )
          )
      ]/Name
      "/>
=================
  <xsl:copy-of select=
   "//BrowseNode
      [not(contains('|Departments|All Products|',
                    concat('|', Name, '|')
                    )
          )
      ]
       /BrowseNodeId
      "/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的 XML 文档时:

<BrowseNodes>
    <BrowseNode>
        <BrowseNodeId>2346727011</BrowseNodeId>
        <Name>Casual</Name>
        <Ancestors>
            <BrowseNode>
                <BrowseNodeId>1045024</BrowseNodeId>
                <Name>Dresses</Name>
                <Ancestors>
                    <BrowseNode>
                        <BrowseNodeId>1040660</BrowseNodeId>
                        <Name>Women</Name>
                        <Ancestors>
                            <BrowseNode>
                                <BrowseNodeId>1036682</BrowseNodeId>
                                <Name>Departments</Name>
                                <IsCategoryRoot>1</IsCategoryRoot>
                                <Ancestors>
                                    <BrowseNode>
                                        <BrowseNodeId>1036592</BrowseNodeId>
                                        <Name>Clothing &amp; Accessories</Name>
                                    </BrowseNode>
                                </Ancestors>
                            </BrowseNode>
                        </Ancestors>
                    </BrowseNode>
                </Ancestors>
            </BrowseNode>
        </Ancestors>
    </BrowseNode>
</BrowseNodes>

计算两个 XPath 表达式,并将其结果(由"========"字符串分隔)复制到输出中

因此,我们可以从转换的结果中验证是否准确选择了所需的NameBrowseNodeId元素:

<Name>Casual</Name>
<Name>Dresses</Name>
<Name>Women</Name>
<Name>Clothing &amp; Accessories</Name>
=================
<BrowseNodeId>2346727011</BrowseNodeId>
<BrowseNodeId>1045024</BrowseNodeId>
<BrowseNodeId>1040660</BrowseNodeId>
<BrowseNodeId>1036592</BrowseNodeId>

在没有看到你的xml是如何构建的情况下,我想出了xpath,我认为你想做的事情。我也不太确定"共享"浏览节点名称的BrowseNodeId,我认为这意味着为所有BrowseNode设置了名称的BrowseNodeId

我在 php 之外组合了您的 xpath,以便更好地可视化它:

/ItemSearchResponse/Items/Item[i]/BrowseNodes//BrowseNode/Name/text()
/ItemSearchResponse/Items/Item[i]/BrowseNodes//BrowseNode/

组合解决方案:

/ItemSearchResponse/Items/Item[i]/BrowseNodes//BrowseNode/Name[text()!='All Products']/text()
/ItemSearchResponse/Items/Item[i]/BrowseNodes//BrowseNode[Name/text()!='All Departments']/BrowseNodeId/text()

PHP解决方案:

$xpath_base='/ItemSearchResponse/Items/Item[';
for ($i = 1; $i<=10; $i++)
  {
    $curr_item_base=$xpath_base.$i.']';
    $bn_name_search=$curr_item_base.'/BrowseNodes//BrowseNode/Name[text()!='All Products']';
    $bn_id_search=$curr_item_base.'/BrowseNodes//BrowseNode[Name/text()!='All Departments']/BrowseNodeId/text()';
    $bn_names=$parsed->xpath($bn_name_search);
    $bn_ids=$parsed->xpath($bn_id_search);
  }

更新要组合 xpath,您可以使用连接|

/ItemSearchResponse/Items/Item[i]/BrowseNodes//BrowseNode[Name/text()!=''Departments'' and Name/text()!=''All Products'']/BrowseNodeId/text() | 
/ItemSearchResponse/Items/Item[i]/BrowseNodes//BrowseNode/Name[text()!=''All Products'' and text()!=''Departments'']

.php:(更新)

$bn_combined_search=$curr_item_base.'/BrowseNodes//BrowseNode[Name/text()!=''Departments'' and Name/text()!=''All Products'']/BrowseNodeId/text() |'.$curr_item_base.'/BrowseNodes//BrowseNode/Name[text()!=''All Products'' and text()!=''Departments'']';

如果我做了一个错误的假设,请发布您的一些xml并详细说明您正在寻找的解决方案。希望这有帮助!