从xpath查询中排除节点

时间:2012-04-20 17:08:34

标签: php xpath simplexml

这是我目前正在使用的一些代码。我需要帮助的地方有$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名称“BrowseNode/Name/”,只有browsnode ID“BrowseNode/BrowseNodeId/”与“BrowseNode/”共享一个“BrowseNode/Name”名称不是“所有产品”我不必测试&lt;Name&gt;Departments&lt;/Name&gt;的存在。如果有ID,则不会为空。如果我可以放两个否定表达式,那就更好了。我会省略名称为“所有产品”的名称和名称为“部门”

的名称

修改 这是XML的一个块:它说“&lt;Name&gt;All Products&lt;/Name&gt;”,我想排除该名称和它的ID。如果我有一个类似“&lt;BrowseNodeId&gt;”的同类词,我也想排除该名称及其ID。 (按ID,我的意思是<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>

{{1}}

3 个答案:

答案 0 :(得分:2)

在没有看到你的xml是如何构造的情况下,我想出了我认为你想要做的事情的xpath。我也不太确定那个“共享”一个browsenode名称的BrowseNodeId,我认为这意味着为所有BrowseNodeId s设置名称设置为BrowseNode

我将你的xpath结合在php之外,以便更好地可视化:

/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并详细说明您正在寻找的解决方案。希望这有帮助!

答案 1 :(得分:2)

你去了:

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

答案 2 :(得分:2)

使用

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

此表达式选择Name个元素的子BrowseNode元素,其字符串值不是字符串"Departments""All Products"之一。

使用

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

这将选择BrowseNodeId元素的子元素,该元素具有BrowseNode兄弟,其字符串值不是字符串Name之一或"Departments"

基于XSLT的验证

"All Products"

在提供的XML文档上应用此转换时:

<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>

评估两个XPath表达式,并将其结果(由<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> 字符串分隔,复制到输出

我们可以从转换结果中验证确切选择了所需的"========"Name元素:

BrowseNodeId