如何使用PHP的SimpleXML对XML属性进行排序?
问题描述
需要对XML中subscriber节点的tariffSpaceName属性进行排序,让同名条目归为一组。尝试用sort()函数时系统提示需传入字符串,当前PHP代码和XML片段如下:
原PHP代码
<?php if (file_exists('2023-04-23-3622216414-5_13324_10_00_100005-s.xml')) { $xml = simplexml_load_file('2023-04-23-3622216414-5_13324_10_00_100005-s.xml'); ?> <html> <table> <tr> <th>tariffSpaceName</th> <th>serviceNumber</th> <th>coreProductNumber</th> </tr> <?php $count = count($xml->subscribers->subscriber); for($aa=0; $aa<$count; $aa++) { foreach($xml->subscribers->subscriber[$aa]->attributes() as $key => $val) { if($key == "tariffSpaceName"){ sort($key); echo "<tr><td>[1]" . $val . "</td>"; } if($key == "serviceNumber"){ echo "<td>[2]" . $val . "</td>"; } if($key == "summaryPriceWithTax"){ echo "<td>[3]" . $val . "</td></tr>"; } } } echo "------<br>"; }else { exit('Failed to open test.xml.'); } ?> </table> </html>
XML片段(单个subscriber节点)
<subscribers> <subscriber accountType="CUST" ownerRefNum="3622216414" ownerCustCode="" phoneNumber="601177068" customerAccountNumber="3622216414" tariffSpaceNumber="5900349478" tariffSpaceName="Böhmová Zdeňka" coreProductNumber="601177068" serviceNumber="601177068" parentServiceNumber="3622216414" serviceStatus="A" summaryPrice="8" summaryPriceTax="1.68" summaryPriceWithTax="9.68" mainTariff="Profil 2" serviceCategory="mobileVoice" noOfEdr="26"> </subscribers>
解决方案
你之前的错误在于直接对属性名字符串$key调用sort()——sort()是用来排序数组的,而且正确逻辑应该是先收集所有subscriber节点,再按tariffSpaceName分组排序。
修正后的代码步骤:
- 遍历所有subscriber节点,提取关键属性存入数组
- 使用
usort()结合多字节字符串比较函数,对数组按tariffSpaceName排序 - 遍历排序后的数组生成表格
修正后的完整代码:
<?php $xmlPath = '2023-04-23-3622216414-5_13324_10_00_100005-s.xml'; if (!file_exists($xmlPath)) { exit('Failed to open XML file.'); } $xml = simplexml_load_file($xmlPath); $subscribers = []; // 收集所有subscriber的关键属性到数组 foreach ($xml->subscribers->subscriber as $subscriber) { $attrs = $subscriber->attributes(); $subscribers[] = [ 'tariffSpaceName' => (string)$attrs->tariffSpaceName, 'serviceNumber' => (string)$attrs->serviceNumber, 'coreProductNumber' => (string)$attrs->coreProductNumber, 'summaryPriceWithTax' => (string)$attrs->summaryPriceWithTax ]; } // 按tariffSpaceName排序,支持带重音的特殊字符 usort($subscribers, function($a, $b) { return mb_strcoll($a['tariffSpaceName'], $b['tariffSpaceName']); }); ?> <html> <table border="1"> <tr> <th>tariffSpaceName</th> <th>serviceNumber</th> <th>coreProductNumber</th> <th>summaryPriceWithTax</th> </tr> <?php foreach ($subscribers as $sub) : ?> <tr> <td><?php echo htmlspecialchars($sub['tariffSpaceName']); ?></td> <td><?php echo htmlspecialchars($sub['serviceNumber']); ?></td> <td><?php echo htmlspecialchars($sub['coreProductNumber']); ?></td> <td><?php echo htmlspecialchars($sub['summaryPriceWithTax']); ?></td> </tr> <?php endforeach; ?> </table> </html>
关键说明
- 原代码中
sort($key)完全无效:$key是属性名字符串,sort()要求传入数组,且这步逻辑和节点排序无关。 - 收集属性时必须用
(string)转换SimpleXML对象,避免后续排序出现类型错误。 - 使用
mb_strcoll而非普通字符串比较,是为了正确处理带重音的字符(比如示例中的Böhmová Zdeňka),保证排序符合语言规则。 - 加入
htmlspecialchars()是为了防止XML中的特殊字符破坏HTML结构,提升页面安全性。
内容的提问来源于stack exchange,提问作者Sneax
相关产品推荐
相关产品推荐

