У меня есть XML-файл, структурированный как
<?xml version="1.0"?> <library> <book id="1003"> <title>Jquery MVC</title> <author>Me</author> <price>500</price> </book> <book id="1001"> <title>Php</title> <author>Me</author> <price>600</price> </book> <book id="1002"> <title>Where to use IFrame</title> <author>Me</author> <price>300</price> </book> </library>
Чтобы отсортировать этот xml в соответствии с идентификатором книги,
после просмотра этого метода из stackoverflow
я закодирован таким образом
$dom = new DOMDocument(); $dom->load('DOM.xml'); $library = $dom->documentElement; $xpath = new DOMXPath($dom); $result = $xpath->query('/library/book'); function sort_trees($t1,$t2){ return strcmp($t1['id'], $t2['id']); } usort($result, 'sort_trees'); print_r($result);*/
Но это дает мне ошибку
Предупреждение: usort () ожидает, что параметр 1 будет массивом, объект указан в /var/www/html/testphp/phpxml/readxml.php в строке 24
Ответ, который вы цитируете для SimpleXML, но вы используете DOMDocument.
Если вы хотите продолжать использовать DOMDocument, вам нужно учесть его API.
$dom = new DOMDocument(); $dom->load('DOM.xml'); $xp = new DOMXPath($dom); $booklist = $xp->query('/library/book'); // Books is a DOMNodeList, not an array. // This is the reason for your usort() warning. // Copies DOMNode elements in the DOMNodeList to an array. $books = iterator_to_array($booklist); // Second, your sorting function is using the wrong API // $node['id'] is SimpleXML syntax for attribute access. // DOMElement uses $node->getAttribute('id'); function sort_by_numeric_id_attr($a, $b) { return (int) $a->getAttribute('id') - (int) $b->getAttribute('id'); } // Now usort() usort($books, 'sort_by_numeric_id_attr'); // verify: foreach ($books as $book) { echo $book->C14N(), "\n"; }
Если вам нужно создать новый выходной документ с отсортированными узлами, создать новый документ, импортировать корневой элемент, затем импортировать узлы книги в отсортированном порядке и добавить в документ.
$newdoc = new DOMDocument('1.0', 'UTF-8'); $libraries = $newdoc->appendChild($newdoc->importNode($dom->documentElement)); foreach ($books as $book) { $libraries->appendChild($newdoc->importNode($book, true)); } echo $newdoc->saveXML();
Однако гораздо лучше использовать XSLT:
<?xml version="1.0" encoding="UTF-8" ?> <!-- file "sort_by_numeric_id.xsl" --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="UTF-8" method="xml" /> <xsl:template match="node()|@*"> <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy> </xsl:template> <xsl:template match="/*"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:apply-templates select="*"> <xsl:sort select="@id" data-type="number"/> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet>
Затем используйте XSLTProcessor (или xsltproc
из командной строки):
$xsltdoc = new DOMDocument(); $xsltdoc->load('sort_by_numeric_id.xsl'); $xslt = new XSLTProcessor(); $xslt->importStyleSheet($xsltdoc); // You can now use $xslt->transformTo*() methods over and over on whatever documents you want $libraryfiles = array('library1.xml', 'library2.xml'); foreach ($libraryfiles as $lf) { $doc = new DOMDocument(); $doc->load($lf); // write the new document $xslt->transformToUri($doc, 'file://'.preg_replace('/(\.[^.]+)?$/', '-sorted$0', $lf, 1); unset($doc); // just to save memory }
с$xsltdoc = new DOMDocument(); $xsltdoc->load('sort_by_numeric_id.xsl'); $xslt = new XSLTProcessor(); $xslt->importStyleSheet($xsltdoc); // You can now use $xslt->transformTo*() methods over and over on whatever documents you want $libraryfiles = array('library1.xml', 'library2.xml'); foreach ($libraryfiles as $lf) { $doc = new DOMDocument(); $doc->load($lf); // write the new document $xslt->transformToUri($doc, 'file://'.preg_replace('/(\.[^.]+)?$/', '-sorted$0', $lf, 1); unset($doc); // just to save memory }
(скопировано из вашего дублированного вопроса) Это работает
$dom = new DOMDocument(); $dom->load('dom.xml'); $xp = new DOMXPath($dom); $booklist = $xp->query('/library/book'); $books = iterator_to_array($booklist); function sort_by_numeric_id_attr($a, $b) { return (int) $a->getAttribute('id') - (int) $b->getAttribute('id'); } usort($books, 'sort_by_numeric_id_attr'); $newdom = new DOMDocument("1.0"); $newdom->formatOutput = true; $root = $newdom->createElement("library"); $newdom->appendChild($root); foreach ($books as $b) { $node = $newdom->importNode($b,true); $root->appendChild($newdom->importNode($b,true)); } $newdom->save('DOM2.xml');
Как вы можете видеть, вам нужно создать новый DOMDocument и добавить к нему отсортированные дочерние элементы (через importNode для копирования DOMNodes из одного DOMDocument в другой).