XML 2 文本问题中的数组标记
XML 2 Array Markup in Text Issue
我正在为以下问题而苦恼。我尝试将 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>
我首先尝试使用简单xml:
$xml = simplexml_load_string($string) or die("Error: Cannot create object");
$json = json_encode($xml);
$array = json_decode($json, TRUE);
但这将 return 包含 "some text , , and some more" 的元素,但没有外部参照的内容。我真正想要的是全文"some text a, b, c and some more",但恐怕我不知道如何实现。
我已经给了 DOMDocument 一个机会,但整个事情都遇到了问题,因为它非常复杂 xml.
有什么想法可以让我收到我想要的东西吗?
编辑:我添加了一个更复杂的 xml 示例。如您所见,我需要遍历各个部分,然后是子部分,然后在其中遍历带有标记和文本的元素。
使用起来非常简单 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
)
SimpleXML 的问题在于它倾向于将文本节点分组为 1 个块。为了能够获得正确拆分的文本,您往往必须使用 DOMDocument。
如您所见,这将加载文档,然后使用 XPath 查找 Element/Text 节点(这只是为了找到正确的点 - 如果您愿意,可以使用 getElementsByTagName()
)。然后在该节点内,它再次使用 XPath 查找所有文本节点(使用 descendant::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;
}
我正在为以下问题而苦恼。我尝试将 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>
我首先尝试使用简单xml:
$xml = simplexml_load_string($string) or die("Error: Cannot create object");
$json = json_encode($xml);
$array = json_decode($json, TRUE);
但这将 return 包含 "some text , , and some more" 的元素,但没有外部参照的内容。我真正想要的是全文"some text a, b, c and some more",但恐怕我不知道如何实现。 我已经给了 DOMDocument 一个机会,但整个事情都遇到了问题,因为它非常复杂 xml.
有什么想法可以让我收到我想要的东西吗?
编辑:我添加了一个更复杂的 xml 示例。如您所见,我需要遍历各个部分,然后是子部分,然后在其中遍历带有标记和文本的元素。
使用起来非常简单 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
)
SimpleXML 的问题在于它倾向于将文本节点分组为 1 个块。为了能够获得正确拆分的文本,您往往必须使用 DOMDocument。
如您所见,这将加载文档,然后使用 XPath 查找 Element/Text 节点(这只是为了找到正确的点 - 如果您愿意,可以使用 getElementsByTagName()
)。然后在该节点内,它再次使用 XPath 查找所有文本节点(使用 descendant::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;
}