【问题标题】:Sorting an XML file using php使用 php 对 XML 文件进行排序
【发布时间】:2022-10-15 01:57:24
【问题描述】:

有一个包含多个条目的 xml 文件,我正在尝试根据两个孩子对其进行排序。 我试图先按 a:DESIGN 排序,然后按 a:COLOR 排序。 我做了各种尝试,但无论我尝试什么都不会排序。 非常感谢任何帮助。

$xml = file_get_contents("http://79.129.20.64:8580/GlxConnector/GetItemsForXml");
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$list = iterator_to_array($xpath->evaluate('/*/*/*'));
uasort(
  $list,
  function($one, $two) use ($xpath) {
    return strcasecmp(
      $xpath->evaluate('string(a:DESIGN)', $one), 
      $xpath->evaluate('string(a:COLOR)', $two)
    );
  } 
);
$document->saveXML();
//var_dump($list);
$document->save('test1.xml');

示例 XML(一些条目仅用于演示。使用真实的键/值):

<GetItemsForXmlResponse xmlns="http://tempuri.org/">
    <GetItemsForXmlResult xmlns:a="http://schemas.datacontract.org/2004/07/e_ShopConnector.Entities" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:ItemForXML>
            <a:AVAILABILITY>false</a:AVAILABILITY>
            <a:CODE>127-0-368-32118-995</a:CODE>
            <a:COLOR>995</a:COLOR>
            <a:DESIGN>32118</a:DESIGN>
            <a:DIMENSION>160X230</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>121.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>BOHEME</a:SERIES>
        </a:ItemForXML>
        <a:ItemForXML>
            <a:AVAILABILITY>true</a:AVAILABILITY>
            <a:CODE>126-0-500-22570-795</a:CODE>
            <a:COLOR>795</a:COLOR>
            <a:DESIGN>22570</a:DESIGN>
            <a:DIMENSION>200X250</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>145.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>SYDNEY</a:SERIES>
        </a:ItemForXML>
        <a:ItemForXML>
            <a:AVAILABILITY>true</a:AVAILABILITY>
            <a:CODE>162-0-120-32118-995</a:CODE>
            <a:COLOR>995</a:COLOR>
            <a:DESIGN>32118</a:DESIGN>
            <a:DIMENSION>080X150</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>40.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>DELUXE</a:SERIES>
        </a:ItemForXML>
        <a:ItemForXML>
            <a:AVAILABILITY>true</a:AVAILABILITY>
            <a:CODE>136-0-252-75002-022</a:CODE>
            <a:COLOR>022</a:COLOR>
            <a:DESIGN>75002</a:DESIGN>
            <a:DIMENSION>140X180</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>76.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>PANAMA</a:SERIES>
        </a:ItemForXML>
        <a:ItemForXML>
            <a:AVAILABILITY>true</a:AVAILABILITY>
            <a:CODE>136-0-252-32118-995</a:CODE>
            <a:COLOR>995</a:COLOR>
            <a:DESIGN>32118</a:DESIGN>
            <a:DIMENSION>140X180</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>76.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>PANAMA</a:SERIES>
        </a:ItemForXML>
    </GetItemsForXmlResponse>
</GetItemsForXmlResult>

预期输出(按设计和颜色排序):

<GetItemsForXmlResponse xmlns="http://tempuri.org/">
    <GetItemsForXmlResult xmlns:a="http://schemas.datacontract.org/2004/07/e_ShopConnector.Entities" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:ItemForXML>
            <a:AVAILABILITY>true</a:AVAILABILITY>
            <a:CODE>162-0-120-32118-995</a:CODE>
            <a:COLOR>995</a:COLOR>
            <a:DESIGN>32118</a:DESIGN>
            <a:DIMENSION>080X150</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>40.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>DELUXE</a:SERIES>
        </a:ItemForXML>
        <a:ItemForXML>
            <a:AVAILABILITY>true</a:AVAILABILITY>
            <a:CODE>136-0-252-32118-995</a:CODE>
            <a:COLOR>995</a:COLOR>
            <a:DESIGN>32118</a:DESIGN>
            <a:DIMENSION>140X180</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>76.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>PANAMA</a:SERIES>
        </a:ItemForXML>
        <a:ItemForXML>
            <a:AVAILABILITY>false</a:AVAILABILITY>
            <a:CODE>127-0-368-32118-995</a:CODE>
            <a:COLOR>995</a:COLOR>
            <a:DESIGN>32118</a:DESIGN>
            <a:DIMENSION>160X230</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>121.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>BOHEME</a:SERIES>
        </a:ItemForXML>
        <a:ItemForXML>
            <a:AVAILABILITY>true</a:AVAILABILITY>
            <a:CODE>126-0-500-22570-795</a:CODE>
            <a:COLOR>795</a:COLOR>
            <a:DESIGN>22570</a:DESIGN>
            <a:DIMENSION>200X250</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>145.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>SYDNEY</a:SERIES>
        </a:ItemForXML>
        <a:ItemForXML>
            <a:AVAILABILITY>true</a:AVAILABILITY>
            <a:CODE>136-0-252-75002-022</a:CODE>
            <a:COLOR>022</a:COLOR>
            <a:DESIGN>75002</a:DESIGN>
            <a:DIMENSION>140X180</a:DIMENSION>
            <a:DISCOUNT_PERCENTAGE>0.000000000000</a:DISCOUNT_PERCENTAGE>
            <a:PRICE>76.000000000000</a:PRICE>
            <a:PRICE_AFTER_DISCOUNT>0.000000000000</a:PRICE_AFTER_DISCOUNT>
            <a:SERIES>PANAMA</a:SERIES>
        </a:ItemForXML>
    </GetItemsForXmlResponse>
</GetItemsForXmlResult>

【问题讨论】:

  • 请编辑您的问题并从示例 xml 添加确切的预期输出。
  • @Jack Fleeting 谢谢。我已经添加了预期的输出。
  • 不确定为什么您认为usort 会改变$document?您正在排序一个名为 $list 的数组,而不是 $document。我猜您需要在保存之前基于$list 重建 XML 文档

标签: php xml


【解决方案1】:

您可以使用powershell

using assembly System
using assembly System.Collections
using assembly System.Xml.Linq

$inputFilename = "c:	emp	est.xml"
$outputFilename = "c:	emp	est1..xml"

$doc = [System.Xml.Linq.XDocument]::Load($inputFilename)
$GetItemsForXmlResult = $doc.Descendants().Where( {$_.Name.LocalName -eq "GetItemsForXmlResult"})

$GetItemsForXmlResult = [System.Linq.Enumerable]::First($GetItemsForXmlResult)

$GetItemsForXmlResult = [System.Xml.Linq.XElement]$GetItemsForXmlResult


$nsA = $GetItemsForXmlResult.GetNamespaceOfPrefix("a")

$sortedtems = $GetItemsForXmlResult.Elements($nsA + "ItemForXML")
$sortedtems = [System.Linq.Enumerable]::ToList($sortedtems)

$sortedtems = $sortedtems | Sort-Object -Property @{ Expression = { $_.Element($nsA + "DESIGN").Value}}, 
                                                  @{ Expression = { $_.Element($nsA + "COLOR").Value}}

$GetItemsForXmlResult.RemoveNodes()
$GetItemsForXmlResult.Add($sortedtems)
$doc.Save($outputFilename)

【讨论】:

  • 非常感谢您的解决方案。我希望使用 php 实时进行排序。
【解决方案2】:

这是可能的——但它非常复杂。恐怕我没有时间完全注释代码,但它基本上涉及创建一个新的骨架文档,在旧文档(使用 xpath)中搜索你的两个键,对它们进行排序,然后从旧文档中导入节点,按该排序顺序,进入新文档。最重要的是,您还必须处理命名空间......

#first - on the old document
$xpath->registerNamespace("a", "http://schemas.datacontract.org/2004/07/e_ShopConnector.Entities");
$designs = $xpath->query('//a:DESIGN/text()');

#create your skeleton new document
$xmlstring = '<GetItemsForXmlResponse xmlns="http://tempuri.org/">
    <GetItemsForXmlResult xmlns:a="http://schemas.datacontract.org/2004/07/e_ShopConnector.Entities" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    </GetItemsForXmlResult>
  </GetItemsForXmlResponse>';
  
$newDoc = new DOMDocument();
$newDoc->loadXML($xmlstring);
$xpath2 = new DOMXPath($newDoc);
$destination = $xpath2->query('//*[local-name()="GetItemsForXmlResult"]');

#and the heavy lifting
foreach($designs as $design) {
    $values[] = $design->nodeValue;
}
$u_des = array_unique(($values));
sort($u_des);
foreach ($u_des as $des){
    $targets = $xpath->query("//a:ItemForXML[.//a:DESIGN/text()= {$des}]");
    foreach ($targets as $target){
        $cols = $xpath->query('.//a:COLOR/text()',$target);
         $col_ar[] = $cols[0]->nodeValue;
          }
          sort($col_ar);
          foreach ($col_ar as $color){
              $finals = $xpath->query("//a:ItemForXML[.//a:DESIGN/text()= {$des}][.//a:COLOR/text()= {$color}]");
              foreach($finals as $final){
                    $node = $newDoc->importNode($final, true);
                    $destination[0]->appendChild($node);
              }
      unset($col_ar);
    }
}
echo $newDoc->saveXML();

在你的实际 xml 上试试这个,看看它是否有效。如果没有,它应该进行一些修补。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 2017-12-28
    • 2017-11-27
    相关资源
    最近更新 更多