我正在尝试过滤掉特定类别的每个XML类别字符串。 我怎么能这样工作?
例如,我只想要类别Category1中的x元素。
示例XML:
<store id="1" name="store">
<species name="stud">
<Category1 name="Category1">
<x category="Hairs" id="20098288"/>
<x category="Hairs" id="20098289"/>
</Category1>
<Category2 name="Category2">
<x category="Shirts" id="24342342"/>
<x category="Shirts" id="24342342"/>
</Category2>
<Category3 name="Category3">
<x category="Jackets" id="423423423"/>
<x category="Jackets" id="423423423"/>
</Category3>
</species>
</store>
我的实际代码,可让我访问每个类别的子元素:
<?php
foreach($xmlDocument->species as $species_elem){
foreach($species_elem->attributes() as $child){
foreach ($child->x as $item){
$itemID = $item->attributes()->id;
}
}
}
?>
但我想指定一个只能访问的类别。例如
$ category ='Category1';
伪代码:
<?php
foreach($species as $species_elem){
foreach($species_elem which contains $Category1 as $category){
foreach ($child->x as $item){
$itemID = $item->attributes()->id;
}
}
}
?>
答案 0 :(得分:1)
XPath将为您节省大量嵌套循环。
//$xml = your xml string;
$category = 'Category1';
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
foreach ($xpath->query("/store/species/$category/x") as $node) {
echo $dom->saveXML($node), "\n";
}
<x category="Hairs" id="20098288"/>
<x category="Hairs" id="20098289"/>
这是通过PHP的DOM extension来完成的,但如果你真的想要,你可以用SimpleXMLElement::xpath做同样的基本事情。
答案 1 :(得分:1)
Paul Crovella的答案很好。 XPath是要走的路。
但是,节点名称不应编号。如果您可以更改格式,我建议将其更改为更通用的格式,例如“类别”。
使用name
属性过滤类别元素。
选择store
文档元素节点:
/store
其species
子元素:
/store/species
任何子元素节点(Category1
,Category2
,...):
/store/species/*
如果属性name
为Category1
:
/store/species/*[@name = 'Category1']
他们的x
子元素:
/store/species/*[@name = 'Category1']/x
在DOM中,您使用DOMXPath::evaluate()
或DOMXPath::query()
在DOM上执行XPath表达式。
$category = 'Category1';
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
foreach ($xpath->evaluate("/store/species/*[@name='$category']/x") as $node) {
echo $dom->saveXML($node), "\n";
}
输出:
<x category="Hairs" id="20098288"/>
<x category="Hairs" id="20098289"/>
SimpleXML使用SimpleXMLElement :: xpath()方法。表达式在元素的上下文中执行。 (store
)并将结果转换为SimpleXMLElement对象数组。
$category = 'Category1';
$element = new SimpleXMLElement($xml);
foreach ($element->xpath("species/*[@name='$category']/x") as $child) {
echo $child->asXml(), "\n";
}
答案 2 :(得分:0)
对于您在问题中提出的XML文档,它实际上非常简单(在您的具体情况下):
$xml = simplexml_load_string($buffer);
foreach ($xml->species->Category1->x as $x) {
echo ' - ', $x->asXML(), "\n";
}
输出:
- <x category="Hairs" id="20098288"/>
- <x category="Hairs" id="20098289"/>
然后,您可以使用类别的变量对此进行参数化:
$category = 'Category1';
foreach ($xml->species->$category->x as $x) {
...
然而,这实际上应该有一些错误处理:
$elements = $xml->species->$category;
if ($elements) foreach ($elements->x as $x) {
echo ' - ', $x->asXML(), "\n";
}
因为变量命名的元素可能并不总是存在。该值将为null
。
完整的例子:
<?php
/**
* PHP foreach loop based filtering on XML document
*
* @link http://stackoverflow.com/q/29280839/367456
*/
$buffer = <<<XML
<store id="1" name="store">
<species name="stud">
<Category1 name="Category1">
<x category="Hairs" id="20098288"/>
<x category="Hairs" id="20098289"/>
</Category1>
<Category2 name="Category2">
<x category="Shirts" id="24342342"/>
<x category="Shirts" id="24342342"/>
</Category2>
<Category3 name="Category3">
<x category="Jackets" id="423423423"/>
<x category="Jackets" id="423423423"/>
</Category3>
</species>
</store>
XML;
$xml = simplexml_load_string($buffer);
foreach ($xml->species->Category1->x as $x) {
echo ' - ', $x->asXML(), "\n";
}
$category = 'Category1';
foreach ($xml->species->$category->x as $x) {
echo ' - ', $x->asXML(), "\n";
}
$elements = $xml->species->$category;
if ($elements) foreach ($elements->x as $x) {
echo ' - ', $x->asXML(), "\n";
}