【问题标题】:PHP XML DOM parseing mixed contentPHP XML DOM 解析混合内容
【发布时间】:2017-01-17 17:57:11
【问题描述】:

我有一个用 XSD 文件很好定义的 XML 文档。 xml文档包含类似如下内容:

<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?

感谢您的帮助。

【问题讨论】:

  • 到目前为止你做了什么?向我们展示代码!
  • 我正在使用 DOMdocument 来查找节点:$xml= new DOMDocument(); $xml->load(XMLPATH); $node = $xml->getElementsByTagName("element")->item(0) 那么下面所有的都忽略嵌套元素: $node->nodeValue $node->C14N();我也按照本指南无济于事:stackoverflow.com/questions/2087103/…
  • @FelippeDuarte 已按要求更新

标签: php xml xpath domdocument


【解决方案1】:

您可以使用 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

【讨论】:

  • 哇这么简单的解决方案,我想我现在必须学习Xpath了。作为一个额外的问题,使用 xpath 导航 domdocument 是否比使用 getelement 方法更快,如果是这样,我很想改造网站的其余部分。
  • 查询是否应该围绕 bar 而不是 foo, I.E '//bar//text() | //bar//元素/@b'。抱歉,如果这不正确,因为我正在尝试获取 XPath
  • 给定输入sn-p,//foo//text() | //foo//element/@b的使用会包含bar元素前后的空白文本节点,不知道你要不要,如果你只使用//bar//text() | //bar//element/@b 结果只有text 2 and some more textJust text
  • 啊,谢谢,有道理,我忘记了 foo 节点将包含文本。我正在将它们处理成一个列表,所以我将使用 //foo 方法来避免普通节点。
【解决方案2】:

以下代码应该让您了解如何在不使用 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;
}

【讨论】:

  • 此解决方案是否会将所有文本内容都放在一个 XML_TEXT_NODE 中,还是嵌套元素会将文本拆分为 2 个 XML_TEXT_NODE?
  • @user2502611 XML DOM 将示例中第一个 元素的内容视为由三个 DOM 节点组成:XML_TEXT_NODE ("text")、XML_ELEMENT_NODE (XML element ) 和 XML_TEXT_NODE ("还有一些文字”)。
猜你喜欢
  • 2016-10-15
  • 2018-06-12
  • 2021-09-19
  • 2016-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多