【问题标题】:Preserve <br> while extracting XML text in PHP在 PHP 中提取 XML 文本时保留 <br>
【发布时间】:2014-11-26 21:44:32
【问题描述】:

我有一个大型 XML 文件,我想对其进行解析并放入数据库。比如这个文件:

<aa>
    <bb>Some text goes here and <br /> some more on a new line
    there are other <junk/> tags that I want to keep ignoring
    </bb>
</aa>

我下面的代码使用 SimpleXML 来解析 bb 标记内的文本内容,但它默默地忽略了 &lt;br /&gt; 标记。如何修改我的代码以接受 &lt;br/&gt; 但不接受 &lt;junk/&gt;

$xml = simplexml_load_file("ab.xml");
foreach( $xml->bb as $bb ) {
    // $bb now contains the text content of the element, but no tags
}

【问题讨论】:

  • 结果应该是:“有些文字放在这里,
    在新行还有一些其他标签,我想继续忽略”
  • 好的,然后编辑剥离的值....echo strip_tags($bb,"&lt;br&gt;"); 现在,它只保留&lt;br&gt; 标签....试试吧,你会发现它会起作用。无论引号内的内容是什么,它都会保留并剥离任何其他标签。相信我!!
  • 当我运行我的代码时,$bb = "Some text goes here and some more on a new line there are other tags that I want to keep ignoring" - 里面没有标签。
  • 不,我将它保存在 MySQL 数据库中。我在查看某些数据的数据库条目时发现了这一点。

标签: php xml simplexml


【解决方案1】:

正如您可以准确地说出要删除哪些元素,通常使用 xpath 最简单的方法是查询这些元素然后删除它们。

在 SimpleXML 中:

$remove = '//junk'; // all <junk> tags anywhere

// simplexml
$sx = simplexml_load_string($xml);
foreach ($sx->xpath($remove) as $element) {
    unset($element->{0});
}

在 DOMDocument 中:

$remove = '//junk'; // all <junk> tags anywhere

// dom
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
foreach ($xpath->query($remove) as $element) {
    $element->parentNode->removeChild($element);
}

完整示例 (Demo):

<?php
/**
 * @link http://stackoverflow.com/a/26318711/367456
 * @link https://eval.in/204702
 */

$xml = <<<BUFFER
<aa>
    <bb>Some text goes here and <br /> some more on a new line
    there are other <junk/> tags that I want to keep ignoring
    </bb>
</aa>
BUFFER;

$remove = '//junk'; // all <junk> tags anywhere

// simplexml
$sx = simplexml_load_string($xml);
foreach ($sx->xpath($remove) as $element) {
    unset($element->{0});
}
$sx->asXML('php://output');

// dom
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
foreach ($xpath->query($remove) as $element) {
    $element->parentNode->removeChild($element);
}
$doc->save('php://output');

输出:

<?xml version="1.0"?>
<aa>
    <bb>Some text goes here and <br/> some more on a new line
    there are other  tags that I want to keep ignoring
    </bb>
</aa>
<?xml version="1.0"?>
<aa>
    <bb>Some text goes here and <br/> some more on a new line
    there are other  tags that I want to keep ignoring
    </bb>
</aa>

【讨论】:

  • 感谢您的示例。垃圾元素会永久删除吗?
  • 是来自文档 - 但不是来自磁盘上的文件。文档在内存中。
  • 我给你的答案是 +1,因为你回答了你自己的问题,这对 SO 很好。
【解决方案2】:

如果您知道要保留哪些标签以及要删除哪些标签,则可以剥离标签。

$xml = simplexml_load_file("ab.xml");
foreach( $xml->bb as $bb ) {
    // This will strip everything but <br>
    echo strip_tags($bb,"<br>");
}

【讨论】:

  • 也许我的措辞不清楚。 $bb 只包含&lt;bb&gt; 的文字内容,所以strip_tags 不会有效果。
  • 如果您想要的产品是:Some text goes here and some more on a new line there are other &lt;junk/&gt; tags that I want to keep ignoring,我所拥有的就可以了。
  • 不是这样的。 $bb 不包含任何标签,它会默默地删除&lt;br/&gt;&lt;junk/&gt;。我希望它保留一个,而不是另一个。
【解决方案3】:

我无法使用 SimpleXML 解决我的问题,但我成功地使用具有递归方法的 DOMElement。请注意,标签选择标准在递归函数内部。

// SimpleXML can be used for the 'simple' cases
$xml = simplexml_load_file("file.xml");
$dom = dom_import_simplexml($xml);
// simpleXML and DOM works with the same underlying data structure, so you can use them interchangably

$aa_content = $xml->aa;
// using simpleXML, $aa is now: "Some text goes here and some more on a new line there are other tags that I want to keep ignoring"
// the <junk> tag is ignore, which is good; but the <br> tag is also ignored, which is bad


// the DOM method
foreach( $dom->childNodes as $node ) {
    $textContent = parsePreserveTags($node);
}

function parsePreserveTags($domNode) {
    // we want to preserve tags (for example, html formatting like <br>)
    $result = '';//$domNode->nodeValue;
    if( $domNode->hasChildNodes() ) {
        foreach( $domNode->childNodes as $node ) {
            // The constant XML_ELEMENT_NODE is defined here http://php.net/manual/en/dom.constants.php
            // If node type is XML_ELEMENT_NODE it's a tag and it can have children.
            // Otherwise, just get the (text) value.
            if( $node->nodeType == XML_ELEMENT_NODE ) {
                // Throw away nodes that match certain criteria
                if( $node->nodeName == 'junk' )
                    continue;

                if( $node->hasChildNodes() ) {
                    // example: "<p>...</p>"
                    $result .= '<' . $node->nodeName . '>' . parsePreserveTags($node)
                        . '</' . $node->nodeName . '>';
                } else {
                    // example: "<br/>"
                    $result .= '<' . $node->nodeName . '/>';
                }
            } else {
                // example: plain text node
                $result .= $node->nodeValue;
            }
        }
    }
    return $result;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多