Php 如何对使用SimpleXML加载的XML文件的内容进行排序?
有一个XML文件,其内容类似于以下内容:Php 如何对使用SimpleXML加载的XML文件的内容进行排序?,php,xml,sorting,Php,Xml,Sorting,有一个XML文件,其内容类似于以下内容: <FMPDSORESULT xmlns="http://www.filemaker.com"> <ERRORCODE>0</ERRORCODE> <DATABASE>My_Database</DATABASE> <LAYOUT/> <ROW MODID="1" RECORDID="1"> <Name>John</Name> <
<FMPDSORESULT xmlns="http://www.filemaker.com">
<ERRORCODE>0</ERRORCODE>
<DATABASE>My_Database</DATABASE>
<LAYOUT/>
<ROW MODID="1" RECORDID="1">
<Name>John</Name>
<Age>19</Age>
</ROW>
<ROW MODID="2" RECORDID="2">
<Name>Steve</Name>
<Age>25</Age>
</ROW>
<ROW MODID="3" RECORDID="3">
<Name>Adam</Name>
<Age>45</Age>
</ROW>
但是代码没有按预期工作。一些SimpleXMLElement方法返回数组,但大多数返回实现迭代器的SimpleXMLElement对象。var_dump()将仅以简化的表示形式显示部分数据。但是,它是一个对象结构,而不是嵌套数组 如果我理解正确,您希望按
名称
子元素对行
元素进行排序。可以使用xpath()
方法获取它们,但需要为名称空间注册前缀。它返回一个SimpleXMLElement对象数组。可以使用usort
对数组进行排序
$fResult = new SimpleXMLElement($xml);
$fResult->registerXpathNamespace('fm', 'http://www.filemaker.com');
$rows = $fResult->xpath('//fm:ROW');
usort(
$rows,
function(SimpleXMLElement $one, SimpleXMLElement $two) {
return strcasecmp($one->Name, $two->Name);
}
);
var_dump($rows);
在DOM中,它看起来没有太大的不同,但是DOMXpath::evaluate()
返回一个DOMNodeList
。您可以使用迭代器\u to\u array
将其转换为数组
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('fm', 'http://www.filemaker.com');
$rows = iterator_to_array($xpath->evaluate('//fm:ROW'));
usort(
$rows,
function(DOMElement $one, DOMElement $two) use ($xpath) {
return strcasecmp(
$xpath->evaluate('normalize-space(Name)', $one),
$xpath->evaluate('normalize-space(Name)', $two)
);
}
);
var_dump($rows);
DOM没有访问子对象和值的神奇方法,可以使用Xpath获取它们。Xpath函数
string()
将第一个节点转换为字符串。如果节点列表为空,则返回空字符串normalize-space()
做的更多。它用一个空格替换所有的空白组,并将其从字符串的开头和结尾剥离。一些SimpleXMLElement方法返回数组,但大多数返回实现迭代器的SimpleXMLElement对象。var_dump()将仅以简化的表示形式显示部分数据。但是,它是一个对象结构,而不是嵌套数组
如果我理解正确,您希望按名称
子元素对行
元素进行排序。可以使用xpath()
方法获取它们,但需要为名称空间注册前缀。它返回一个SimpleXMLElement对象数组。可以使用usort
对数组进行排序
$fResult = new SimpleXMLElement($xml);
$fResult->registerXpathNamespace('fm', 'http://www.filemaker.com');
$rows = $fResult->xpath('//fm:ROW');
usort(
$rows,
function(SimpleXMLElement $one, SimpleXMLElement $two) {
return strcasecmp($one->Name, $two->Name);
}
);
var_dump($rows);
在DOM中,它看起来没有太大的不同,但是DOMXpath::evaluate()
返回一个DOMNodeList
。您可以使用迭代器\u to\u array
将其转换为数组
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('fm', 'http://www.filemaker.com');
$rows = iterator_to_array($xpath->evaluate('//fm:ROW'));
usort(
$rows,
function(DOMElement $one, DOMElement $two) use ($xpath) {
return strcasecmp(
$xpath->evaluate('normalize-space(Name)', $one),
$xpath->evaluate('normalize-space(Name)', $two)
);
}
);
var_dump($rows);
DOM没有访问子对象和值的神奇方法,可以使用Xpath获取它们。Xpath函数
string()
将第一个节点转换为字符串。如果节点列表为空,则返回空字符串normalize-space()
做的更多。它用一个空格替换所有组的空白,并从字符串的开头和结尾将其剥离。我建议使用DOM扩展,因为它更灵活:
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->load('xml1.xml');
// Get the root node
$root = $doc->getElementsByTagName('FMPDSORESULT');
if (!$root->length)
die('FMPDSORESULT node not found');
$root = $root[0];
// Pull the ROW tags from the document into an array.
$rows = [];
$nodes = $root->getElementsByTagName('ROW');
while ($row = $nodes->item(0)) {
$rows []= $root->removeChild($row);
}
// Sort the array of ROW tags
usort($rows, function ($a, $b) {
$a_name = $a->getElementsByTagName('Name');
$b_name = $b->getElementsByTagName('Name');
return ($a_name->length && $b_name->length) ?
strcmp(trim($a_name[0]->textContent), trim($b_name[0]->textContent)) : 0;
});
// Append ROW tags back into the document
foreach ($rows as $row) {
$root->appendChild($row);
}
// Output the result
echo $doc->saveXML();
输出
将行追加回文档中:
$root = $xpath->evaluate('/myns:FMPDSORESULT')[0];
foreach ($rows as $row) {
$root->appendChild($row);
}
我建议使用DOM扩展,因为它更灵活:
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->load('xml1.xml');
// Get the root node
$root = $doc->getElementsByTagName('FMPDSORESULT');
if (!$root->length)
die('FMPDSORESULT node not found');
$root = $root[0];
// Pull the ROW tags from the document into an array.
$rows = [];
$nodes = $root->getElementsByTagName('ROW');
while ($row = $nodes->item(0)) {
$rows []= $root->removeChild($row);
}
// Sort the array of ROW tags
usort($rows, function ($a, $b) {
$a_name = $a->getElementsByTagName('Name');
$b_name = $b->getElementsByTagName('Name');
return ($a_name->length && $b_name->length) ?
strcmp(trim($a_name[0]->textContent), trim($b_name[0]->textContent)) : 0;
});
// Append ROW tags back into the document
foreach ($rows as $row) {
$root->appendChild($row);
}
// Output the result
echo $doc->saveXML();
输出
将行追加回文档中:
$root = $xpath->evaluate('/myns:FMPDSORESULT')[0];
foreach ($rows as $row) {
$root->appendChild($row);
}
你说得对,DOM更加灵活和强大。但我建议在任何情况下都使用Xpath:-)@嗯,我喜欢XPath,但在这种特殊情况下,我认为它不会显著改进代码。你是对的,DOM更加灵活和强大。但我建议在任何情况下都使用Xpath:-)@我喜欢XPath,但在这种特殊情况下,我认为它不会显著改进代码。