SimpleXML:处理节点值中存在的 CDATA 标记
SimpleXML: handle CDATA tag presence in node value
我在解析 XML 文档时需要保存 <![CDATA[]]>
标签。
比如我有节点:
<Dest><![CDATA[some text...]]></Dest>
在 xml 文件中可能存在没有 CDATA 的节点。
然后我循环处理所有节点:
$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
$nodeValue = (string) $child;
}
因此,当我在上面的示例中处理节点时 - $nodeValue
= some text...
但是我需要$nodeValue
= <![CDATA[some text...]]>
有什么办法吗?
文件示例:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
<Params>
<param>text</param>
<anotherParam>text</anotherParam>
</Params>
<Content>
<String>
<Source>some another text</Source>
<Dest>some another text 2</Dest>
</String>
<String>
<Source>some another text 3</Source>
<Dest><![CDATA[some text...]]></Dest>
</String>
</Content>
</Root>
如果您想将 CDATA 添加到所有没有 CDATA 的元素,您可以这样做:
$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
if(strpos((string) $child,'CDATA')){
$nodeValue = (string) $child)
}
else {
$nodeValue = "<![CDATA[".((string) $child)."]]>";
}
}
这样你就可以 $nodeValue = '<![CDATA[some text...]]>'
如果你只想拥有有 CDATA 的元素,你可以这样做:
$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
if(strpos((string) $child,'CDATA')){
$nodeValue = (string) $child;
}
}
这样你就可以 $nodeValue = '<![CDATA[some text...]]>'
如果您想要没有 CDATA 的元素并添加它,您可以这样做:
$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
if(!strpos((string) $child,'CDATA')){
$notValue ="<![CDATA[".((string) $child)."]]>";
}
}
你将拥有 $nodeValue = '<![CDATA[some another text 3]]>'
就像 SimpleXML 这样的解析器而言,<![CDATA[
不是 XML 元素的文本内容的一部分,它只是序列化的一部分内容。这里讨论了类似的混淆:PHP, SimpleXML, decoding entities in CDATA
您需要查看的是该元素的 "inner XML",这在 SimpleXML 中很棘手(->asXML()
会给您 "outer XML",例如 <Dest><![CDATA[some text...]]></Dest>
).
这里最好的选择是使用 the DOM,这样您就可以更多地访问文档的详细 [=23=] 结构 ,而不是试图给您 content,所以区分"text nodes"和"CDATA nodes"。但是,值得仔细检查您是否确实需要它,对于 99.9% 的用例,您不应该关心是否有人向您发送 <foo>bar & baz</foo>
或 <foo><![CDATA[bar & baz]]></foo>
,因为根据定义它们代表相同字符串。
我在解析 XML 文档时需要保存 <![CDATA[]]>
标签。
比如我有节点:
<Dest><![CDATA[some text...]]></Dest>
在 xml 文件中可能存在没有 CDATA 的节点。
然后我循环处理所有节点:
$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
$nodeValue = (string) $child;
}
因此,当我在上面的示例中处理节点时 - $nodeValue
= some text...
但是我需要$nodeValue
= <![CDATA[some text...]]>
有什么办法吗?
文件示例:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
<Params>
<param>text</param>
<anotherParam>text</anotherParam>
</Params>
<Content>
<String>
<Source>some another text</Source>
<Dest>some another text 2</Dest>
</String>
<String>
<Source>some another text 3</Source>
<Dest><![CDATA[some text...]]></Dest>
</String>
</Content>
</Root>
如果您想将 CDATA 添加到所有没有 CDATA 的元素,您可以这样做:
$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
if(strpos((string) $child,'CDATA')){
$nodeValue = (string) $child)
}
else {
$nodeValue = "<![CDATA[".((string) $child)."]]>";
}
}
这样你就可以 $nodeValue = '<![CDATA[some text...]]>'
如果你只想拥有有 CDATA 的元素,你可以这样做:
$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
if(strpos((string) $child,'CDATA')){
$nodeValue = (string) $child;
}
}
这样你就可以 $nodeValue = '<![CDATA[some text...]]>'
如果您想要没有 CDATA 的元素并添加它,您可以这样做:
$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
if(!strpos((string) $child,'CDATA')){
$notValue ="<![CDATA[".((string) $child)."]]>";
}
}
你将拥有 $nodeValue = '<![CDATA[some another text 3]]>'
就像 SimpleXML 这样的解析器而言,<![CDATA[
不是 XML 元素的文本内容的一部分,它只是序列化的一部分内容。这里讨论了类似的混淆:PHP, SimpleXML, decoding entities in CDATA
您需要查看的是该元素的 "inner XML",这在 SimpleXML 中很棘手(->asXML()
会给您 "outer XML",例如 <Dest><![CDATA[some text...]]></Dest>
).
这里最好的选择是使用 the DOM,这样您就可以更多地访问文档的详细 [=23=] 结构 ,而不是试图给您 content,所以区分"text nodes"和"CDATA nodes"。但是,值得仔细检查您是否确实需要它,对于 99.9% 的用例,您不应该关心是否有人向您发送 <foo>bar & baz</foo>
或 <foo><![CDATA[bar & baz]]></foo>
,因为根据定义它们代表相同字符串。