使用php Simple XML获取节点的文本部分

时间:2011-02-27 08:39:30

标签: php simplexml

鉴于php代码:

$xml = <<<EOF
<articles>
<article>
This is a link
<link>Title</link>
with some text following it.
</article>
</articles>
EOF;

function traverse($xml) {
    $result = "";
    foreach($xml->children() as $x) {
        if ($x->count()) {
            $result .= traverse($x);
        }
        else {
            $result .= $x;
        }
    }
    return $result;
}

$parser = new SimpleXMLElement($xml);
traverse($parser);

我期望函数traverse()返回:

This is a link Title with some text following it.

但是,它仅返回:

Title

有没有办法使用simpleXML获得预期的结果(显然是为了消耗数据而不是像在这个简单的例子中那样返回它)?

谢谢, Ñ

7 个答案:

答案 0 :(得分:17)

有些方法可以通过SimpleXML实现您想要的功能,但在这种情况下,最简单的方法是使用DOM。好消息是,如果您已经在使用SimpleXML,则不需要更改任何内容,因为DOM和SimpleXML是basically interchangeable

// either
$articles = simplexml_load_string($xml);
echo dom_import_simplexml($articles)->textContent;

// or
$dom = new DOMDocument;
$dom->loadXML($xml);
echo $dom->documentElement->textContent;

假设您的任务是迭代每个<article/>并获取其内容,您的代码将如下所示

$articles = simplexml_load_string($xml);
foreach ($articles->article as $article)
{
    $articleText = dom_import_simplexml($article)->textContent;
}

答案 1 :(得分:4)

node->asXML();// It's the simple solution i think !!

答案 2 :(得分:3)

因此,我的问题的简单答案是:Simplexml无法处理这种XML。请改用DomDocument。

此示例显示如何遍历整个XML。似乎DomDocument可以使用任何XML,而SimpleXML要求XML很简单。

function attrs($list) {
    $result = "";
    foreach ($list as $attr) {
        $result .= " $attr->name='$attr->value'";
    }
    return $result;
}

function parseTree($xml) {
    $result = "";
    foreach ($xml->childNodes AS $item) {
        if ($item->nodeType == 1) {
            $result .= "<$item->nodeName" . attrs($item->attributes) . ">" . parseTree($item) . "</$item->nodeName>";
        }
        else {
            $result .= $item->nodeValue;
        }
    }
    return $result;
}

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

print parseTree($xmlDoc->documentElement);

您还可以使用simpleXML加载xml,然后使用dom_import_simplexml()将其转换为DOM,如Josh所说。如果您使用simpleXml过滤节点进行解析,这将非常有用,例如:使用XPath。

但是,我实际上并没有使用simpleXML,所以对我而言,这需要很长时间。

$simpleXml = new SimpleXMLElement($xml);
$xmlDom = dom_import_simplexml($simpleXml);

print parseTree($xmlDom);

感谢您的帮助!

答案 3 :(得分:1)

只需将字符串视为字符串,就可以获得带有simplexml的DOM元素的文本节点:

foreach($xml->children() as $x) {
   $result .= "$x"

然而,打印出来:

This is a link

with some text following it.
TitleTitle

..因为文本节点被视为一个块,并且无法分辨子项在文本节点内的位置。由于其他{},子节点也会被添加两次,但您可以将其取出。

很抱歉,如果我没有帮助,但我认为没有办法找出子节点在文本节点中的位置,除非xml是一致的(但是,为什么不使用标签)。如果您知道要删除文本的元素,strip_tags()将会很有效。

答案 4 :(得分:1)

这已经得到了解答,但是CASTING TO STRING(即$ sString =(string)oSimpleXMLNode-&gt; TagName)总是对我有效。

答案 5 :(得分:0)

就像@tandu所说,这是不可能的,但是如果你可以修改你的XML,这将有效:

$xml = <<<EOF
<articles>
    <article>
        This is a link
    </article>
    <link>Title</link>
    <article>
       with some text following it.
    </article>
</articles>

答案 6 :(得分:0)

试试这个:

$parser = new SimpleXMLElement($xml);
echo strip_tags($parser->asXML());

这几乎相当于:

$parser = simplexml_load_string($xml);
echo dom_import_simplexml($parser)->textContent;