我正在使用SimpleXML解析PHP中的XML,并具有如下所示的XML:
<xml>
<element>
textpart1
<subelement>subcontent1</subelement>
textpart2
<subelement>subcontent2</subelement>
textpart3
</element>
</xml>
当我执行$xml-> element时,它自然会给我整个元素,就像所有三个文本部分一样.
因此,如果我将其解析为一个数组(为孩子使用foreach),则会得到:
0 => textpart1textpart2textpart3, 1 => subcontent1, 2 => subcontent2
我需要一种方法来解析< element>节点,以便将在子元素处停止或开始的每个文本部分视为自己的元素.
结果,我正在寻找可以在这样的数组中表达的有序列表:
0 => textpart1, 1 => subcontent1, 2 => textpart2, 3 => subcontent2, 4 => textpart3
在不更改XML文件的情况下有可能吗?预先感谢您的任何提示!
解决方法:
就像其他人所说的那样,SimpleXML不支持将单独的文本节点作为单独的实体访问,因此您将需要使用一些DOM方法对其进行补充.幸运的是,您可以使用dom_import_simplexml
和simplexml_import_dom
在两者之间随意切换.
您需要的DOM功能的关键部分是:
> DOMElement-> childNodes成员变量,以可迭代列表的形式直接访问特定元素下的所有节点
> DOMNode-> nodeType变量,用于确定特定子项是文本节点还是元素
> DOMNode-> nodeValue变量以获取实际文本
有了这些,您可以编写一个函数,该函数返回一个数组,其中包含用于子元素的SimpleXML对象和用于子文本节点的字符串的混合物,如下所示:
function get_child_elements_and_text_nodes($sx_element)
{
$return = array();
$dom_element = dom_import_simplexml($sx_element);
foreach ( $dom_element->childNodes as $dom_child )
{
switch ( $dom_child->nodeType )
{
case XML_TEXT_NODE:
$return[] = $dom_child->nodeValue;
break;
case XML_ELEMENT_NODE:
$return[] = simplexml_import_dom($dom_child);
break;
}
}
return $return;
}
在您的情况下,您需要递归该树,如果您在混合使用DOM和SimpleXML时使它有些混乱,因此您可以改为在DOM中完全编写递归并在运行它之前转换SimpleXML对象:
function recursively_find_text_nodes($dom_element)
{
$return = array();
foreach ( $dom_element->childNodes as $dom_child )
{
switch ( $dom_child->nodeType )
{
case XML_TEXT_NODE:
$return[] = $dom_child->nodeValue;
break;
case XML_ELEMENT_NODE:
$return = array_merge($return, recursively_find_text_nodes($dom_child));
break;
}
}
return $return;
}
$text_nodes = recursively_find_text_nodes(dom_import_simplexml($simplexml->element));
Here’s a live demo of that last function.