当值存在时,PHP获取XML节点属性

时间:2015-04-06 17:19:28

标签: php simplexml

我想获取整个XML内容,但结果只显示节点值,节点属性丢失。

XML文件:

<main>
    <people num="1">
        <name num1="1">Jack</name>
        <age num2="1">50</age>
    </people>   
</main>

代码是

$xml = simplexml_load_file("c:/www/Mongo/test2.xml");
$xml1=$xml->people;
var_dump($xml1);

结果:

object(SimpleXMLElement)#2 (3) { ["@attributes"]=> array(1) { ["num"]=>string(1) "1" } ["name"]=> string(4) "Jack" ["age"]=> string(2) "50" }

缺少名称和年龄节点属性。 我知道属性可以通过$ xml-&gt; people-&gt;名称获得,但如何获取它只能使用$ xml-&gt;人

2 个答案:

答案 0 :(得分:1)

问题是叶节点(例如名称)可以同时具有属性(num1 = "1")和值("Jack")。转换成数组时应该如何表示?

如果我们设置$array['people']['name'] = "Jack",我们会在哪里存储属性?我们不能使用$array['people']['name']['@attributes'] = ['num1' => 1],因为这会覆盖&#34; Jack&#34;值。

下面的代码提供了一种解决方案,其中每个(叶子)值都包含在'value'元素中,例如$array['people']['name']['value'] = "Jack"并且属性具有标准'@attributes'密钥,例如$array['people']['name']['@attributes'] = ['num1' => 1]。这适用于简单的XML,如问题中的那个,但可能不适用于更复杂的文档。

阅读评论我明白你实际上想要将XML转换为JSON,所以这就是下面代码最终的作用:

// Some example XML (some elements added)
$src = <<<EOS
<main>
    <people num="1">
        <name num1="1">Jack</name>
        <age num2="1">50</age>
        <skills what="ever">
            <skill type="minor">Cookie munching</skill>
            <skill type="major">Cake gobbling</skill>
            <skill>Candy gulping</skill>
        </skills>
    </people>
</main>
EOS;

// Create a DOM element from XML    
$dom = new DOMDocument();
$dom->loadXML($src);

// Use a XPath query to get all leaf nodes (elements without
// element child nodes)
$xpath = new DOMXPath($dom);
foreach ($xpath->query('//*[not(*)]') as $leaf) {
    // Create a new <value> element for each leaf node, moving
    // the leaf value (first child) into that node.
    // E.g. <name num1="1">Jack</name>
    //   => <name num1="1"><value>Jack</value></name>
    $value = $dom->createElement('value');
    $value->appendChild($leaf->firstChild);
    $leaf->insertBefore($value);
}

// Turn into SimpleXMLElement and covert to JSON
$xml  = simplexml_import_dom($dom);
$json = json_encode($xml, JSON_PRETTY_PRINT);
echo $json, PHP_EOL;

输出:

{
    "people": {
        "@attributes": {
            "num": "1"
        },
        "name": {
            "@attributes": {
                "num1": "1"
            },
            "value": "Jack"
        },
        "age": {
            "@attributes": {
                "num2": "1"
            },
            "value": "50"
        },
        "skills": {
            "@attributes": {
                "what": "ever"
            },
            "skill": [
                {
                    "@attributes": {
                        "type": "minor"
                    },
                    "value": "Cookie munching"
                },
                {
                    "@attributes": {
                        "type": "major"
                    },
                    "value": "Cake gobbling"
                },
                {
                    "value": "Candy gulping"
                }
            ]
        }
    }
}

答案 1 :(得分:0)

这是使用json_encode,json_decode

的更好的解决方案
echo '<pre>';
$xml = simplexml_load_file("n.xml");
$xml=json_decode(json_encode($xml),TRUE);
$xml1=$xml['people'];
print_r($xml1);
echo '<br>';
print_r($xml['people']['@attributes']['num']);

输出

Array
(
    [@attributes] => Array
        (
            [num] => 1
        )

    [name] => Jack
    [age] => 50
)

1

所以最后一个建议,可能你可以像这样改变你的XML数据

<?xml version="1.0" encoding="UTF-8"?>
<main>
    <people num="1">
        <name num1="1"><first_name>Jack</first_name></name>
        <age num2="1"><years>50</years></age>
    </people>   
</main>

输出:

    Array
(
    [people] => Array
        (
            [@attributes] => Array
                (
                    [num] => 1
                )

            [name] => Array
                (
                    [@attributes] => Array
                        (
                            [num1] => 1
                        )

                    [first_name] => Jack
                )

            [age] => Array
                (
                    [@attributes] => Array
                        (
                            [num2] => 1
                        )

                    [years] => 50
                )

        )

)

这对你有用。 :)