php / simplexml-LIBXML选项是否被忽略?

问题描述 投票:1回答:2

我正在尝试将LIBXML *常量用于SimpleXMLElement构造函数的第二个参数,但它们根本没有任何改变。

$xml = '<root><empty_tag/><foo></foo></root>';
$simpleXml = new SimpleXMLElement($xml, LIBXML_NOENT|LIBXML_NOXMLDECL|LIBXML_NOEMPTYTAG);

$simpleXml->foo = 'Ņ';

echo $simpleXml->asXML();

预期:

<root><empty_tag></empty_tag><foo>Ņ</foo></root>

实际:

<?xml version="1.0"?>
<root><empty_tag/><foo>&#x145;</foo></root>

如您所见,这些标志中没有一个做任何事情-实体仍然被转义(即使XML仅应根据"'&><来转义https://www.w3.org/TR/xml/#syntax),XML声明仍然存在,并且空标记保持为空。有没有一种使用SimpleXML达到预期结果的方法?还是至少只能逃避5个特殊字符? addChild()在这里不是选项,我要分配现有的节点。

php simplexml libxml2
2个回答
2
投票

这些常量的命名可能有点神秘。那么实际上支持什么呢?

LIBXML_NOENT

是将实体添加为对文档的实体引用,还是对其进行了扩展。需要通过加载文档来指定:

<?php

$xml = '<!DOCTYPE test [<!ENTITY c "TEST">]>
<test>&c;</test>';

echo (new SimpleXMLElement($xml))->asXML(), "\n";
echo (new SimpleXMLElement($xml, LIBXML_NOENT))->asXML(), "\n";

这显示第一个输出:

<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY c "TEST">
]>
<test>&c;</test>

实体已保留。对于第二个回显,使用LIBXML_NOENT

<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY c "TEST">
]>
<test>TEST</test>

XML是从相关的问答中借来的:What does LIBXML_NOENT do (and why isn't it called LIBXML_ENT)?

顺便说一下,这与文档中包含的非US-ASCII字符无关。如果需要带有文档的文档,请将编码设置为UTF-8,例如:

$xml = '<root><empty_tag/><foo></foo></root>';
$simpleXml = new SimpleXMLElement($xml);

dom_import_simplexml($simpleXml)->ownerDocument->encoding = 'UTF-8';

$simpleXml->foo = 'Ņ';

echo $simpleXml->asXML();

这里的诀窍是set the encoding in the underlying DOMDocument,这是我知道DOMDocument(和SimpleXMLElement)的唯一方法。这里的输出:

DOMDocument

您再也看不到<?xml version="1.0" encoding="UTF-8"?> <root><empty_tag/><foo>Ņ</foo></root> 实体,而只能看到Unicode(UTF-8编码)中的&#x145;Ņ现在也显示编码。

根据您的问题,我想这就是您在寻找XML declaration的目的。

LIBXML_NOXMLDECL

列表中的第二个。我从未使用过它,它的确有错误,并且/或者有一些特定的版本要求,但是老实说,我什至不知道是否有意/在哪里应用它。

您可以从输出中删除包含XML声明的第一行(始终以“ LIBXML_NOENT”终止)。

或者您可以再次与基础\n相关联以输出文档元素,因此它不是完整的文档,因此没有XML声明:

DOMDocument

输出:

$dom = dom_import_simplexml($simpleXml)->ownerDocument;
echo $dom->saveXML($dom->documentElement);

这基本上是在<root><empty_tag/><foo>Ņ</foo></root> 中建议的内容。

LIBXML_NOEMPTYTAG

列表中的第三个也是最后一个。我现在可以引用PHP手册,但这已经在remove xml version tag when a xml is created in php其他地方完成了,但是无论如何,无论常量不可用,如何使用on site already来做到这一点?

一种方法是再次通过SimpleXMLElement提供选项:

DOMDocument

输出:

$dom = dom_import_simplexml($simpleXml)->ownerDocument;
echo $dom->saveXML($dom->documentElement, LIBXML_NOEMPTYTAG);

或为了执行此“纯” SimpleXML,将空文本节点插入每个空元素:

<root><empty_tag></empty_tag><foo>Ņ</foo></root>

即在$xml = '<?xml version="1.0" encoding="UTF-8"?><root><empty_tag/><foo></foo></root>'; $simpleXml = new SimpleXMLElement($xml); $simpleXml->foo = 'Ņ'; foreach ($simpleXml->xpath('//*[not(*) and string() = ""]') as $empty) { $empty[0] = ''; } echo $simpleXml->asXML(); 中,以获取每个xpath查询的所有空元素,然后将其文本内容设置为一个空字符串,如果不存在(空),则将在其中插入一个文本节点然而。输出:

foreach

我希望这会为您提供所需的选项。


1
投票

您将需要添加XML文档是使用UTF-8编码的事实,所以类似...

<?xml version="1.0" encoding="UTF-8"?>
<root><empty_tag></empty_tag><foo>Ņ</foo></root>

给你...

$xml = '<?xml version="1.0" encoding="utf-8" ?><root><empty_tag/><foo></foo></root>';
© www.soinside.com 2019 - 2024. All rights reserved.