我有以下 XML:
<?xml version="1.0"?>
<STATUS_LIST>
<ORDER_STATUS SORDER_CODE="SO001" ASSOCIATED_REF="001">
<INVOICES>
<INVOICE INVOICE_CODE="???">SOMETHING</INVOICE>
</INVOICES>
</ORDER_STATUS>
</STATUS_LIST>
当我运行以下代码时:
$statuses = simplexml_load_string($result); //Where $result is my XML
if (!empty($statuses))
{
foreach ($statuses as $status)
{
foreach ($status->INVOICES as $invoice)
{
echo (string)$invoice->attributes()->INVOICE_CODE;
}
}
}
我单步执行此代码,我可以看到针对
ORDER_STATUS
的属性,但我无法看到针对INVOICE
的属性。不过,我可以看到发票上的价值 SOMETHING
。
知道什么可能导致这种情况吗?
更新
经过一些测试,如果我将元素添加到
INVOICE
元素中,我可以获得显示的属性,因此如果我使用此 xml 来代替,它将起作用:
<?xml version="1.0"?>
<STATUS_LIST>
<ORDER_STATUS SORDER_CODE="SO001" ASSOCIATED_REF="001">
<INVOICES>
<INVOICE INVOICE_CODE="???"><TEST>tester</TEST></INVOICE>
</INVOICES>
</ORDER_STATUS>
</STATUS_LIST>
所以它有里面有一个元素来获取属性!?
根据过去的问题,“SimpleXML 不允许在同一元素上使用属性和文本。”这非常荒谬,我找不到任何关于这一事实的官方报道,但这似乎是真的。瘸。这是有效的 XML。我知道 Perl SimpleXML 读起来很好。
您的问题与没有内容的元素无关,您只是循环定义稍有错误。
当您编写
foreach ($status->INVOICES as $invoice)
时,SimpleXML 将循环遍历 $status
元素的每个子元素(称为 INVOICES
);在这种情况下,总会有一个这样的元素。但您真正想要的是循环该元素的所有 children - 各个 INVOICE
节点。
为此,您可以使用以下方法之一:
foreach ($status->INVOICES->children() as $invoice)
(循环遍历第一个元素的所有子节点,在本例中仅循环 INVOICES
元素)foreach ($status->INVOICES[0]->children() as $invoice)
(相同,但更明确地选择第一个 INVOICES
节点)foreach ($status->INVOICES[0] as $invoice)
(实际上又做了同样的事情:因为您专门选择了一个节点,然后要求循环,SimpleXML 假设您想要它的子节点;这就是为什么 foreach($statuses as $status)
用作外循环)foreach ($status->INVOICES->INVOICE as $invoice)
(仅循环名为 INVOICE
的子节点,恰好是所有子节点)就个人而言,我会重写您的示例循环如下:
foreach ($statuses->ORDER_STATUS as $status)
{
foreach ($status->INVOICES->INVOICE as $invoice)
{
echo (string)$invoice['INVOICE_CODE'];
}
}
记录在案(PHP 8.1)
$xml='<?xml version="1.0"?>
<STATUS_LIST>
<ORDER_STATUS SORDER_CODE="SO001" ASSOCIATED_REF="001">
<INVOICES>
<INVOICE INVOICE_CODE="???">SOMETHING</INVOICE>
</INVOICES>
</ORDER_STATUS>
</STATUS_LIST>';
$statuses = simplexml_load_string($xml);
var_dump($statuses)
结果:
object(SimpleXMLElement)#1 (1) {
["ORDER_STATUS"]=>
object(SimpleXMLElement)#2 (2) {
["@attributes"]=>
array(2) {
["SORDER_CODE"]=>
string(5) "SO001"
["ASSOCIATED_REF"]=>
string(3) "001"
}
["INVOICES"]=>
object(SimpleXMLElement)#3 (1) {
["INVOICE"]=>
string(9) "SOMETHING"
}
}
}
属性发票 INVOICE_CODE="???"不可用。
所以@Dan Goodspeed 是对的
解决方案:
$str = preg_replace('/<([^ ]+) ([^>]*)>([^<>]*)<\/\\1>/i', '<$1 $2><value>$3</value></$1>', $string);