文本问题中的XML 2数组标记

时间:2019-05-24 07:34:25

标签: php xml simplexml

我正在努力解决以下问题。我尝试将xml文档转换为PHP中的数组,到目前为止效果很好。但是我确实有一些特殊元素,其中包含带有标记的文本。元素看起来像这样:

<section>
    <name>sectionname</name>
    <subsection>
        <subsectionname>one</subsectionname>
        <element>
            <text>some text <xref>a</xref>, <xref>b</xref>, <xref>c</xref></text>
        </element>
    </subsection>
    <subsection>
        <subsectionname>two</subsectionname>
        <element>
            <text>some text <xref>a</xref>, <xref>b</xref>, <xref>c</xref></text>
        </element>
    </subsection>
</section>

我首先尝试使用simplexml:

$xml = simplexml_load_string($string) or die("Error: Cannot create object");
$json = json_encode($xml);
$array = json_decode($json, TRUE);

但是这将返回一个包含“一些text,还有一些more”而没有外部参照内容的元素。我真正想要的是全文“一些文本a,b,c以及更多”,但恐怕我不知道该如何实现。 而且我已经试过了DOMDocument,但是由于它是一个非常复杂的xml,所以整个过程都出现了问题。

有什么想法可以收到我想要的东西吗?

编辑:我添加了一个更复杂的xml示例。如您所见,我将需要遍历各节,然后遍历小节,并在其中遍历带有标记和文本的元素。

2 个答案:

答案 0 :(得分:1)

SimpleXML的问题在于它倾向于将文本节点分为1个块。为了获得正确分割的文本,您通常必须使用DOMDocument。

如您所见,这将加载文档,然后使用XPath查找Element / Text节点(这只是为了达到正确的目的-您可以根据需要使用getElementsByTagName())。然后,在该节点内,它再次使用XPath查找所有文本节点(使用descendant::text()),然后将依次从文档中的<text>节点获取每个文本。

对于每个Text节点,这将创建一个空白的$text字符串,并将其内容添加到循环中,然后将其显示...

$data = '<section>
    <name>sectionname</name>
    <subsection>
        <subsectionname>one</subsectionname>
        <element>
            <text>some text <xref>a</xref>, <xref>b</xref>, <xref>c</xref></text>
        </element>
    </subsection>
    <subsection>
        <subsectionname>two</subsectionname>
        <element>
            <text>some text <xref>a</xref>, <xref>b</xref>, <xref>c</xref>d</text>
        </element>
    </subsection>
</section>';

$dom = new DOMDocument();
$dom->loadXML($data);
$xp = new DOMXPath($dom);
foreach ( $xp->query("//element/text") as $element ) {
    $text = '';
    foreach ( $xp->query("descendant::text()", $element) as $textNode )    {
        $text .= $textNode->textContent;
    }   
    echo $text.PHP_EOL;
}

这将显示(我修改了第二个来帮助)...

some text a, b, c
some text a, b, cd

编辑:

正如ThW所指出的那样,使用textContent将获取包括子节点在内的所有文本,因此您可以将内部循环缩短为

foreach ( $xp->query("//element/text") as $element ) {
    echo $element->textContent.PHP_EOL;
}

答案 1 :(得分:0)

使用DOMDocument相当容易-如果我正确理解了这个问题,则可以尝试这样〜尽管由于XML的片段很小,所以标记可能会很宽泛

<?php

    $strxml='<?xml version="1.0" encoding="UTF-8"?>
        <root>
            <element>
                <text>some text <xref>a</xref>, <xref>b</xref>, <xref>c</xref> and some more</text>
            </element>
            <element>
                <text>a banana <xref>FFF</xref>, <xref>GGG</xref>, <xref>ZZZ</xref> and some more bananas</text>
            </element>
        </root>';

    $dom=new DOMDocument;
    $dom->loadXML( $strxml );

    $col=$dom->getElementsByTagName('element');
    $output=array();

    foreach( $col as $node )$output[]=$node->childNodes[1]->nodeValue;


    printf('<pre>%s</pre>',print_r( $output, true ) );

?>

将输出

Array
(
    [0] => some text a, b, c and some more
    [1] => a banana FFF, GGG, ZZZ and some more bananas
)