【问题标题】:XML 2 Array Markup in Text Issue [duplicate]文本问题中的 XML 2 数组标记 [重复]
【发布时间】:2019-05-24 07:34:25
【问题描述】:

我正在努力解决以下问题。我尝试将 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);

但是这将返回一个包含“一些文本,,等等”的元素,而没有外部参照的内容。我真正想要的是整个文本“一些文本a,b,c等等”,但恐怕我不知道如何实现这一点。 我已经给了 DOMDocument 一个机会,但是因为它是一个非常复杂的 xml,所以对整个事情有问题。

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

编辑:我添加了一个更复杂的 xml 示例。如您所见,我需要遍历部分,然后是子部分,然后是带有标记和文本的元素。

【问题讨论】:

    标签: php xml simplexml


    【解决方案1】:

    SimpleXML 的问题在于它倾向于将文本节点分成 1 个块。为了能够正确拆分文本,您往往必须使用 DOMDocument。

    如您所见,这会加载文档,然后使用 XPath 查找元素/文本节点(这只是为了找到正确的点 - 如果您愿意,可以使用 getElementsByTagName())。然后在该节点内,它再次使用 XPath 查找所有文本节点(使用 descendant::text()),然后依次从文档中的 &lt;text&gt; 节点获取每段文本。

    对于每个 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;
    }
    

    【讨论】:

    【解决方案2】:

    使用DOMDocument 很容易——如果我理解正确的问题,你可以这样尝试~ 虽然只有一小部分 XML 的 sn-p,这可能有点过分

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

    【讨论】:

    • 感谢您的回复。在这个简单的例子中,这很好用,但是当它变得更复杂时我仍然遇到困难。我用更复杂的 xml 更新了我的问题。我的问题是遍历元素然后获取所需的数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多