[英]Get ancestor node with PHP and xpath
Please forgive if the following is a bit muddled, I've been killing myself trying to work this out. 请原谅如果以下有点混乱,我一直在努力解决这个问题。
This is a chunk of XML (exported from a much large site) that I am using to create a category tree for a mini-CMS. 这是我用来为mini-CMS创建类别树的一大块XML(从一个大型站点导出)。 Once I've got the value and name of the node, which is no problem, I also need to get the 'parent' each node, that is, the node preceding it which is above it in the hierarchy. 一旦我获得了节点的值和名称,这没有问题,我还需要获得每个节点的“父”,即层次结构中位于它之上的节点。
<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>
For example, for the productCategory-genericName DCinemaLens , I need to be able to grab the parent as DigitalCinema , and similarly for the individual productModel nodes, where the parent would be DCinemaProj . 例如,对于productCategory-genericName DCinemaLens ,我需要能够将父级抓取为DigitalCinema ,对于单个productModel节点,其中父级将是DCinemaProj 。
I've tried various different queries in xpath using ancestor, previous-sibling and parent and I still can't see to grab the node I need. 我已经尝试使用祖先,前兄弟和父亲在xpath中进行各种不同的查询,但我仍然看不到抓住我需要的节点。
Here is my code as it stands from giving up on my attempts a few minutes ago. 这是我的代码,因为几分钟前放弃了我的尝试。
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>';
}
}
I've also had some success getting information in an array, but it always just returns every value in the XML again. 我在数组中获取信息也取得了一些成功,但它总是只返回XML中的每个值。
$key = 'genericName';
$derpgleep = $derp[$key];
echo 'Derp= ' . $derpgleep;
print_r($derp);
Hopefully there is a really easy solution I am overlooking. 希望我能忽略一个非常简单的解决方案。 I hope I have been clear. 我希望我已经清楚了。
The XPath expression you are using: 您正在使用的XPath表达式:
ancestor::productCategory[1]/genericName
would work if you were able to perform that expression starting from the current node. 如果你能够从当前节点开始执行该表达式将会工作。 this is not possible indeed starting from the current Array $genericName
as it does not contain parents, nor ancestors. 从当前的Array $genericName
开始,这是不可能的,因为它不包含父类,也不包含祖先。
I think that your option is to re-traverse all the XML tree. 我认为您的选择是重新遍历所有XML树。 This is a sample test which works as required, based on your input sample. 这是一个样本测试,根据您的输入样本,根据需要运行。
<?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";
}
}
?>
This will print out the following HTML fragment: 这将打印出以下HTML片段:
<p align='center'>DigitalCinema - (genericName) </p>
<p align='center'>DCinemaProj - (genericName) DigitalCinema</p>
<p align='center'>DCinemaLens - (genericName) DigitalCinema</p>
While to get the "parent" of productModel you need an xpath like: 要获得productModel的“父”,您需要一个xpath,如:
$derp = $xml->xpath("//productModel[.='" .
$productModel[0] .
"']/parent::productCategory[1]/genericName");
Use (supposing the initial context node is either a productCategory[genericName = 'DCinemaLens']
or a productModel
): 使用 (假设初始上下文节点是productCategory[genericName = 'DCinemaLens']
或productModel
):
../preceding-sibling::*[1]
XSLT-based verification : 基于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>
when this transformation is applied on the provided XML document : 当此转换应用于提供的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>
the wanted two elements are copied to the output : 想要的两个元素被复制到输出 :
<genericName>DigitalCinema</genericName>
-------------
<genericName>DCinemaProj</genericName>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.