PHP使用唯一属性解析嵌套XML

时间:2014-01-19 08:39:09

标签: php xml parsing recursion

我有一个嵌套的XML,我需要遍历并获取不仅是节点,还有属性键和值,它们各不相同。

我尝试在PHP中编写一个递归函数来获取我想要的东西。我的XML看起来如下......

<document>
<character>
    <literal>name</literal>
    <codepoint>
        <cp_value cp_type="ucs">4e9c</cp_value>
        <cp_value cp_type="jis208">16-01</cp_value>
    </codepoint>
    <radical>
        <rad_value rad_type="classical">7</rad_value>
        <rad_value rad_type="nelson_c">1</rad_value>
    </radical>
            <meaning_group>
                <meaning>this</meaning>
                <meaning>that</meaning>
            </meaning_group>
     </character>
    ...
</document>

问题是并非所有[character]节点都具有完全相同的子节点。

我试图将属性键和值组合成一个键,然后将该值作为值关联。如果没有属性,我想使用标签名称作为密钥。此外,一些孩子具有相同的名称,没有属性。在这种情况下,我想将它们放在由换行符分隔的一个字段中。谢谢!

["literal"] => "name",
["cp_type-ucs"] => "4e9c",
["cp_type-jis208"] => "16-01",
["rad_type-classical"] => "7",
["rad_type-nelson_c"] => "1",
["meaning"] => "this\nthat"

那是我要输出的数组......

任何和所有帮助将不胜感激!谢谢!

编辑:添加了一些代码,我可以使用它遍历各个层并获取标记名称以回显,但由于某种原因,它们不会填充数组。只有“character”标签才会出现在数组中。

    function ripXML($file) {
    $xml = simplexml_load_file ( $file );
    return (peelTags ( $xml , array()) );
}
function peelTags($node, $tag) {
// find if there are children. (IF SO, there shouldn't be
$numChildren = @count ( $node->children () );

if ($numChildren != 0) {
    foreach ( $node->children () as $child ) {
        $tag [] = $child->getName ();
        peelTags ( $child, $tag);

        echo "<br />Name = " . $child->getName ();
    }
} 
    return $tag;
}

$file = "dictionarytest.xml";
print_r ( ripXML ( $file ) );

编辑2 - 我终于明白了。它可能有点乱,而不是最好的方法,但它解决了我面临的问题。如果其他人需要类似的东西,这里就是!

$_SESSION ["a"] = array ();
$_SESSION ["c"] = 0;
function ripXML($file) {
$xml = simplexml_load_file ( $file );
return (peelTags ( $xml, array () ));
}
function peelTags($node, $tag) {
// find if there are children. (IF SO, there shouldn't be
$numChildren = @count ( $node->children () );

if ($numChildren != 0) {
    foreach ( $node->children () as $child ) {
        peelTags ( $child, $tag );
        $tag = $child->getName ();
        if ($tag == "literal") {
            $_SESSION ["c"] ++;
        }
        $value = trim($child->__toString ());
        if (isset ( $value ) && $value != "") {
            if ($child->attributes ()) {
                foreach ( $child->attributes () as $k => $v ) {
                    if (isset ( $v ) && $v != "") {
                        $_SESSION ["a"] [$_SESSION ["c"]] [$k . "_" . $v] = $value;
                    } 
                }
            } else {
                $_SESSION ["a"] [$_SESSION ["c"]] [$tag] = $value;
            }
        }
    }
}
return 1;
}

$file = "dictionarytest.xml";
print_r ( ripXML ( $file ) );
print_r ( $_SESSION ["a"] );

我使用全局会话变量来存储递归算法的数组和计数器。我不知道是否有人有更好的建议。如果可能的话,我想优化这个功能。我在仅有5个条目的XML文件上测试它,但我的真实文件将超过4000个。

1 个答案:

答案 0 :(得分:1)

......令人困惑。我没有语法检查或测试这个,但我认为它是这样的......

$domd=new DOMDocument();
$domd->loadXML($xml);
$interestingdomnode=$domd->getElementsByTagName("character")->item(0);
$parsed_info=array();
$parsed_info['literal']=$interestingdomnode->getElementsByTagName("literal")->item(0)->textContent;
foreach($interestingdomnode->getElementsByTagName("cp_value") as $cp){
$parsed_info["cp_type-".$cp->cp_type]=$cp->textContent
}
foreach($interestingdomnode->getElementsByTagName("rad_type") as $cp){
$parsed_info["rad_type-".$cp->rad_type]=$cp->textContent
}
$parsed_info['meaning']='';
foreach($interestingdomnode->getElementsByTagName("meaning") as $cp){
$parsed_info['meaning'].=$cp->textContent.PHP_EOL;
}
var_dump($parsed_info);