PHP XML DOM解析混合内容

问题描述:

我有一个用XSD文件定义好的XML文档。 XML文档包含类似以下内容:PHP XML DOM解析混合内容

<foo> 
    <bar>text <element a="1" b="2" c="3" /> and some more text</bar> 
    <bar>Just text</bar> 
</foo> 

我想用PHP解析它只是带回一个属性值(将其他地方的代码来决定)内嵌的休息文中,这个例子我想“B”,输出应该是:

"text 2 and some more text" 
"Just text" 

我有得到输出这种格式的问题,我不能找到一种方法,无论是拆分节点文本,以便我可以插入属性值或输出节点的纯xml。

我的首选是使用PHP的DOMDocument方法来做到这一点。虽然我还没有学习XPath,但我会愿意学习它,如果它能使这个任务成为可能的话。我也会考虑改变嵌套节点的格式,尽管这是最后的手段。

我使用的DOMDocument找到节点:

$xml= new DOMDocument(); 
$xml->load(XMLPATH); 
$node = $xml->getElementsByTagName("element")->item(0); 

则以下所有的的忽略嵌套元素:

$node->nodeValue; 
$node->C14N(); 

我也遵循这个指南无济于事: How to get innerHTML of DOMNode?

感谢您的帮助。

+2

到目前为止你做了什么?向我们展示代码! –

+0

我正在使用DOMdocument来查找节点: $ xml = new DOMDocument(); $ xml-> load(* XMLPATH *); $ node = $ xml-> getElementsByTagName(“element”) - > item(0) 然后以下所有内容都会忽略嵌套元素: $ node-> nodeValue $ node-> C14N(); 我也遵循这个指南无济于事: http://*.com/questions/2087103/how-to-get-innerhtml-of-domnode – user2502611

+0

@FelippeDuarte根据要求更新 – user2502611

您可以使用XPath来选择text()节点和@b选择属性和联合运营|将把所有以正确的顺序:

$xml = <<<EOD 
<foo> 
    <bar>text <element a="1" b="2" c="3" /> and some more text</bar> 
    <bar>Just text</bar> 
</foo> 
EOD; 

$doc = new DOMDocument(); 
$doc->loadXML($xml); 

$xpath = new DOMXPath($doc); 
$nodeList = $xpath->query('//foo//text() | //foo//element/@b', $doc); 

$result = ''; 

for ($i = 0; $i < $nodeList->length; $i++) { 
    $result .= $nodeList[$i]->textContent; 
} 
echo $result; 

结果是

text 2 and some more text 
    Just text 
+0

哇这样一个简单的解决方案,我猜我将不得不学习Xpath。 作为一个额外的问题,它会更快导航domdocument使用xpath而不是getelement方法,如果是的话,我很想改造其余的网站。 – user2502611

+0

查询应该围绕bar而不是foo,I.E'// bar // text()| // //杆元件/ @ B”。对不起,如果这是不正确的,因为我试图拿起XPath – user2502611

+0

给定输入片段,使用'//foo // text()| // foo // element/@ b'将在'bar'元素之前,之间和之后包含空白文本节点,我不知道你是否想要它们,如果你只使用'// bar // text )| // bar // element/@ b'结果只是'text 2和更多text_text'。 –

以下代码应该让你知道如何在不使用XPath的情况下实现你的目标:

<?php 
$xml = '<foo> 
    <bar>text <element a="1" b="2" c="3" /> and some more text</bar> 
    <bar>Just text</bar> 
</foo>'; // Your example XML. 

$attr = 'b'; // Attribute of <element> you are interested in. 

$doc = new DOMDocument(); 
$doc->loadXml($xml); 

foreach($doc->documentElement->getElementsByTagName('bar') as $bar) 
{ 
    $text = ''; 
    foreach($bar->childNodes as $child) 
    { 
     switch($child->nodeType) 
     { 
     case XML_ELEMENT_NODE: 
      if($child->nodeName == 'element') 
       $text .= $child->getAttribute($attr); 
      break; 
     case XML_TEXT_NODE: 
      $text .= $child->textContent; 
      break; 
     } 
    } 
    echo $text . PHP_EOL; 
} 
+0

此解决方案是否将所有文本内容都包含在单个XML_TEXT_NODE中,或者嵌套元素是否将文本拆分为2个XML_TEXT_NODE? – user2502611

+0

@ user2502611 XML DOM将您的示例中第一个元素的内容视为由三个DOM节点组成:XML_TEXT_NODE(“text”),XML_ELEMENT_NODE(XML元素)和XML_TEXT_NODE(“以及更多文本”)。 – PowerGamer