【问题标题】:PHP parse XML within XMLPHP 在 XML 中解析 XML
【发布时间】:2014-09-10 09:41:50
【问题描述】:

我有一个 XML 文件,其中包含 XML。我将如何将所有内容解析为数组或对象?

<DATA>
    <ROW>
        <id>1</id>
        <message_id>123456789</message_id>
        <brand_name>SAMPLE</brand_name>
        <request_xml>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;Email&gt;
&lt;Service&gt;
&lt;LogMessage/&gt;
&lt;Delivery&gt;
&lt;Synchronous/&gt;
&lt;/Delivery&gt;
&lt;/Service&gt;
&lt;Model&gt;
&lt;Head&gt;
&lt;From&gt;someone@example.com &lt;/From&gt;
&lt;To&gt;someone@sample.com&lt;/To&gt;
&lt;Subject&gt;Your Question&lt;/Subject&gt;
&lt;/Head&gt;
&lt;ns2:ContactUs&gt;
&lt;ns2:Sender&gt;
&lt;ns2:FirstName&gt;John&lt;/ns2:FirstName&gt;
&lt;/ns2:Sender&gt;
&lt;/ns2:ContactUs&gt;
&lt;/Model&gt;
&lt;InlineImages/&gt;
&lt;History/&gt;
&lt;/Email&gt;
        </request_xml>
        <http_status>400</http_status>
        <created_by>admin</created_by>
        <created_on>2014-09-08 01:56:59</created_on>
    </ROW>
</DATA>

我的目标是最终得到类似的东西:

SimpleXMLElement Object
(
    [ROW] => SimpleXMLElement Object
        (
            [id] => 1
            [message_id] => 123456789
            [brand_name] => SAMPLE
            [request_xml] => SimpleXMLElement Object
                (
                    ...
                    [LogMessage] => 
                    ...
                    [from] => someone@example.com
                    ...
                )

            [http_status] => 400
            [created_by] => admin
            [created_on] => 2014-09-08 01:56:59
        )
)

我没有在我的示例中放置request_xml 的所有级别,但你明白了。基本上我希望 request_xml 像 XML 文件的其余部分一样被解析。

我怎样才能做到这一点?提前感谢您对此提供的任何帮助!

【问题讨论】:

  • 为什么不只解析 SimpleXML 中的主字符串,提取子字符串,将其解析为 SimpleXML 并将子 XML 作为节点添加到主 XML?
  • 我将如何处理编码?
  • 您可以将html_entity_decodestr_replace 与一组特定的实体一起使用。
  • 为了处理编码,我最终使用了simplexml_load_string($xmlfile, 'SimpleXMLElement', LIBXML_NOENT);,所以我不需要使用html_entity_decode

标签: php xml


【解决方案1】:

如果你读取request_xml元素节点的节点值,结果会解码实体。

$outer = new DOMDocument();
$outer->loadXml($xml);
$xpath = new DOMXpath($outer);

$innerXml = $xpath->evaluate('string(/DATA/ROW/request_xml)');
echo $innerXml;

输出:

<?xml version="1.0" encoding="UTF-8"?>
<Email>
<Service>
<LogMessage/>
...

您可以将内部 xml 加载到单独的文档对象中。

$inner = new DOMDocument();
$inner->loadXml(trim($innerXml));
echo $inner->saveXml();

但在您的示例中,内部 XML 已损坏。它缺少 ns2 前缀的命名空间定义。如果添加它将起作用:

演示:https://eval.in/191279

【讨论】:

  • 感谢您的回答。我在我的问题中省略了名称空间定义,但它实际上就在那里。但是由于某种原因,simplexml_load_string() 无法解析这些 ns2 标签。但这不是一个大问题。我真正关心的是字段的内容,所以我可以在解析之前对标签进行快速str_replace
  • SimpleXMLs 命名空间处理有点复杂,您可以使用 SimpleXMLElement::registerXpathNamespace() 注册自己的前缀并将它们与 xpath() 一起使用,其中一些方法也是命名空间感知的。但它只对那个元素有效,在子元素上你必须再次注册它们。 DOM 为 Xpath 使用单独的对象,因此您只需注册一次。 stackoverflow.com/a/25571382/2265374
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
  • 2013-06-20
  • 1970-01-01
  • 1970-01-01
  • 2014-09-29
相关资源
最近更新 更多