我正在尝试筛选出特定类别的每个XML类别字符串。我该怎么做?
例如,我只想要类别1中的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='类别1';
伪代码:
<?php
foreach($species as $species_elem){
foreach($species_elem which contains $Category1 as $category){
foreach ($child->x as $item){
$itemID = $item->attributes()->id;
}
}
}
?>
但是,节点名称不应编号。如果你能改变格式,我建议把它们改成更通用的格式,比如"类别"。
使用name
属性可以筛选类别元素。
XPath逐步
选择store
文档元素节点:/store
其species
子元素:/store/species
任何子元素节点(Category1
、Category2
…):/store/species/*
如果属性name
为Category1
:/store/species/*[@name = 'Category1']
它们的x
子元素:/store/species/*[@name = 'Category1']/x
DOM
在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
SimpleXML使用SimpleXMLElement::xpath()方法。表达式是在元素的上下文中执行的。(store
),并且结果被转换为SimpleXMLElement对象的数组。
$category = 'Category1';
$element = new SimpleXMLElement($xml);
foreach ($element->xpath("species/*[@name='$category']/x") as $child) {
echo $child->asXml(), "n";
}
对于您在问题中提出的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";
}