2011-09-05 138 views
4

请原谅如果以下情况有点混乱,我一直在试图解决这个问题。使用PHP和xpath获取祖先节点

这是我用来为迷你CMS创建类别树的一大块XML(从大型网站导出)。一旦我得到了节点的值和名称,这是没有问题的,我还需要获取每个节点的“父”,也就是它在层次结构之上的节点之前的节点。

<productCategory> 
    <genericName>DigitalCinema</genericName> 
    <productCategories> 
     <productCategory> 
     <genericName>DCinemaProj</genericName> 
     <productModels> 
      <productModel>ProjProd-1</productModel> 
      <productModel>ProjProd-2</productModel> 
      <productModel>ProjProd-3</productModel> 
      <productModel>ProjProd-4</productModel> 
     </productModels> 
     </productCategory> 
     <productCategory> 
     <genericName>DCinemaLens</genericName> 
     </productCategory> 
    </productCategories> 
    </productCategory> 

例如,对于产品分类,genericName DCinemaLens,我需要能够抓住家长为DigitalCinema,同样为个人产品型号节点,如果母公司将DCinemaProj

我已经尝试了xpath中使用祖先,前兄弟姐妹和父母的各种不同的查询,我仍然看不到抢我需要的节点。

这是我的代码,因为它放弃了我几分钟前的尝试。

if ($xml->xpath('//productCategories')) { 

    foreach($xml->xpath('//genericName | //productModel') as $genericName){ 

    echo "<p align='center'>$genericName"; 

    $type = $genericName->getName(); 

    echo " - (" . $type . ") "; 

    $derp = $xml->xpath("ancestor::productCategory[1]/genericName"); 

    echo $derp; 

    echo '</p>'; 

    } 

    } 

我也有一些成功在阵列获取信息,但它始终只是再次返回的XML的每个值。

$key = 'genericName'; 

    $derpgleep = $derp[$key]; 

    echo 'Derp= ' . $derpgleep; 

    print_r($derp); 

希望有一个非常简单的解决方案,我忽略了。我希望我已经清楚。您正在使用

+0

好问题,+1。查看我的答案,获得一个完整,简短且简单的XPath表达式,用于选择所需的,称为“父”节点。 –

回答

2

XPath表达式:如果你能够执行表达式从当前节点开始

ancestor::productCategory[1]/genericName 

会工作。从目前的数组$genericName开始,这是不可能的,因为它不包含父母,也不包含祖先。

我认为你的选择是重新遍历所有的XML树。根据您的输入样本,这是一个根据需要运行的样本测试。

<?php 
$xml = simplexml_load_file("test_input1.xml"); 

if ($xml->xpath('//productCategories')) { 

    foreach($xml->xpath('//genericName') as $genericName){ 

     echo "<p align='center'>$genericName"; 

     $type = $genericName->getName(); 

     echo " - (" . $type . ") "; 

     $derp = $xml->xpath("//genericName[.='" . 
      $genericName[0] . 
      "']/ancestor::productCategory[2]/genericName"); 

     echo $derp[0]; echo "</p>\n"; 
    } 
} 
?> 

这将打印出以下HTML片段:

<p align='center'>DigitalCinema - (genericName) </p> 
<p align='center'>DCinemaProj - (genericName) DigitalCinema</p> 
<p align='center'>DCinemaLens - (genericName) DigitalCinema</p> 

虽然得到的“父” 产品型号你需要的XPath,如:

 $derp = $xml->xpath("//productModel[.='" . 
      $productModel[0] . 
      "']/parent::productCategory[1]/genericName"); 
+2

不能够感谢你足够的empo,这正是我所需要的。脚本现在完美无缺! – PenguinOfwar

+1

哇,这是一个很好的结果,因为这是我第一次尝试php。我得到了一些XPath的帮助。 –

1

使用 (假设初始上下文节点是productCategory[genericName = 'DCinemaLens']productModel):

../preceding-sibling::*[1] 

基于XSLT的验证

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:copy-of select= 
    "/*/*/productCategory 
      [genericName = 'DCinemaLens'] 
       /../preceding-sibling::*[1]"/> 
------------- 
<xsl:text/> 
    <xsl:copy-of select= 
    "/*/*/*/*/productModel/../preceding-sibling::*[1]"/> 
</xsl:template> 
</xsl:stylesheet> 

当这个变换所提供的XML文档施加:

<productCategory> 
    <genericName>DigitalCinema</genericName> 
    <productCategories> 
     <productCategory> 
      <genericName>DCinemaProj</genericName> 
      <productModels> 
       <productModel>ProjProd-1</productModel> 
       <productModel>ProjProd-2</productModel> 
       <productModel>ProjProd-3</productModel> 
       <productModel>ProjProd-4</productModel> 
      </productModels> 
     </productCategory> 
     <productCategory> 
      <genericName>DCinemaLens</genericName> 
     </productCategory> 
    </productCategories> 
</productCategory> 

的通缉两个元件被复制到输出

<genericName>DigitalCinema</genericName> 
------------- 
<genericName>DCinemaProj</genericName>