[英]Get ancestor node with PHP and xpath
請原諒如果以下有點混亂,我一直在努力解決這個問題。
這是我用來為mini-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>
例如,對於productCategory-genericName DCinemaLens ,我需要能夠將父級抓取為DigitalCinema ,對於單個productModel節點,其中父級將是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);
希望我能忽略一個非常簡單的解決方案。 我希望我已經清楚了。
您正在使用的XPath表達式:
ancestor::productCategory[1]/genericName
如果你能夠從當前節點開始執行該表達式將會工作。 從當前的Array $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>
要獲得productModel的“父”,您需要一個xpath,如:
$derp = $xml->xpath("//productModel[.='" .
$productModel[0] .
"']/parent::productCategory[1]/genericName");
使用 (假設初始上下文節點是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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.