You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用simplexml_load_string解析XML时属性丢失问题

Fixing XML Attribute Loss When Converting to Array in PHP

Ah, I’ve hit this exact problem countless times! The issue with your current simplexml_load_string() → JSON → array workflow is that SimpleXML stores XML attributes in a special @attributes key, but converting via JSON can flatten or obscure these values depending on your XML’s structure. Let’s break down the solutions:

Why Attributes Go Missing

When you run json_encode($xml), the SimpleXMLElement’s attributes get serialized into an @attributes sub-array. For simple XML, you might find them buried there, but for nested or complex structures, this can get messy or even lost entirely if the element has child nodes. For example, this XML:

<product sku="ABC123">
  <name>Wireless Headphones</name>
  <price currency="USD">99.99</price>
</product>

Would turn into an array where sku is in $array['@attributes'] and currency is in $array['price']['@attributes']—easy to miss if you’re expecting attributes to be at the same level as the element’s content.

Solution 1: Quick Fix for Simple XML

If your XML structure is straightforward, you can manually merge the @attributes into the parent array. Here’s how:

$xml = simplexml_load_string($value);
$json = json_encode($xml);
$array = json_decode($json, TRUE);

// Recursively merge attributes into their parent elements
function mergeAttributes(&$array) {
    if (isset($array['@attributes'])) {
        $array = array_merge($array['@attributes'], $array);
        unset($array['@attributes']);
    }
    foreach ($array as &$item) {
        if (is_array($item)) {
            mergeAttributes($item);
        }
    }
}

mergeAttributes($array);

This will pull all attributes up to the same level as the element’s other data, making them easier to access.

Solution 2: Robust Recursive Conversion (Best for Complex XML)

For more reliable results—especially with nested elements, repeated node names, or mixed text + attributes—use a custom recursive function to convert the SimpleXMLElement directly to an array, preserving all attributes and structure:

function xmlToArray(\SimpleXMLElement $xml, $prefixAttributes = '@') {
    $result = [];

    // Add attributes first
    foreach ($xml->attributes() as $attrName => $attrValue) {
        $result[$prefixAttributes . $attrName] = (string)$attrValue;
    }

    // Handle child nodes
    foreach ($xml->children() as $childName => $childNode) {
        // If multiple children share the same name, convert to an array
        if (isset($result[$childName])) {
            if (!is_array($result[$childName]) || !array_key_exists(0, $result[$childName])) {
                $result[$childName] = [$result[$childName]];
            }
            $result[$childName][] = xmlToArray($childNode, $prefixAttributes);
        } else {
            $result[$childName] = xmlToArray($childNode, $prefixAttributes);
        }
    }

    // Add text content if the node has it (and isn't just empty whitespace)
    $textContent = trim((string)$xml);
    if (!empty($textContent)) {
        if (empty($result)) {
            // Node is just text, return directly
            return $textContent;
        } else {
            // Node has both text and children/attributes
            $result['#text'] = $textContent;
        }
    }

    return $result;
}

// Usage example
$xml = simplexml_load_string($value);
$array = xmlToArray($xml);

This function:

  • Preserves all attributes (you can customize the prefix or remove it entirely by changing $prefixAttributes)
  • Handles repeated child nodes by converting them into indexed arrays
  • Keeps text content intact, even when mixed with attributes or child nodes

Final Notes

Avoid the JSON middleman if you can—it’s a shortcut that sacrifices structure integrity. The recursive function approach is far more reliable for real-world XML scenarios.

内容的提问来源于stack exchange,提问作者Drupal Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:00:17