奇怪的#text 字符串的解释
奇怪的#text 字符串不是突然出现的,而是实际的文本节点。当您加载带有 DOM 任何空格的格式化 XML 文档时,例如默认情况下,缩进、换行和节点值将作为 DOMText 实例作为 DOM 的一部分,例如
<cellphones>\n\t<telefon>\n\t\t<model>Easy DB…
E T E T E T
其中 E 是 DOMElement,T 是 DOMText。
要解决这个问题,请像这样加载文档:
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->load('file.xml');
那么你的文档结构如下
<cellphones><telefon><model>Easy DB…
E E E T
请注意,代表 DOMElement 值的各个节点仍将是 DOMText 实例,但控制格式的节点已消失。稍后会详细介绍。
证明
您可以使用以下代码轻松测试:
$dom = new DOMDocument;
$dom->preserveWhiteSpace = TRUE; // change to FALSE to see the difference
$dom->load('file.xml');
foreach ($dom->getElementsByTagName('telefon') as $telefon) {
foreach($telefon->childNodes as $node) {
printf(
"Name: %s - Type: %s - Value: %s\n",
$node->nodeName,
$node->nodeType,
urlencode($node->nodeValue)
);
}
}
此代码遍历给定 XML 中的所有 telefon 元素,并打印出节点名称、类型和它的子节点的 urlencoded 节点值。当你保留空白时,你会得到类似的东西
Name: #text - Type: 3 - Value: %0A++++
Name: model - Type: 1 - Value: Easy+DB
Name: #text - Type: 3 - Value: %0A++++
Name: proizvodjac - Type: 1 - Value: Alcatel
Name: #text - Type: 3 - Value: %0A++++
Name: cena - Type: 1 - Value: 25
Name: #text - Type: 3 - Value: %0A++
…
我对值进行 urlencoded 的原因是为了表明实际上存在 DOMText 节点,其中包含 DOMDocument 中的缩进和换行符。 %0A 是一个换行符,而每个 + 是一个空格。
当您将其与您的 XML 进行比较时,您会看到在每个 <telefon> 元素之后有一个换行符,后跟四个空格,直到 <model> 元素开始。同样,在结束<cena> 和开始<telefon> 之间只有一个换行符和两个空格。
这些节点的给定类型是 3,即 - according to the list of predefined constants - 是 XML_TEXT_NODE,例如DOMText 节点。由于缺少正确的元素名称,这些节点的名称为#text。
忽略空格
现在,当您禁用保留空白时,上面将输出:
Name: model - Type: 1 - Value: Easy+DB
Name: proizvodjac - Type: 1 - Value: Alcatel
Name: cena - Type: 1 - Value: 25
Name: model - Type: 1 - Value: 3310
…
如您所见,没有更多的#text 节点,而只有type 1 节点,这意味着XML_ELEMENT_NODE,例如DOMElement。
DOMElements 包含 DOMText 节点
我一开始说过,DOMElements 的值也是DOMText 实例。但是在上面的输出中,它们无处可寻。那是因为我们正在访问nodeValue 属性,该属性将DOMText 的值作为字符串返回。我们可以很容易地证明该值为DOMText:
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML($xml);
foreach ($dom->getElementsByTagName('telefon') as $telefon) {
$node = $telefon->firstChild->firstChild; // 1st child of model
printf(
"Name: %s - Type: %s - Value: %s\n",
$node->nodeName,
$node->nodeType,
urlencode($node->nodeValue)
);
}
会输出
Name: #text - Type: 3 - Value: Easy+DB
Name: #text - Type: 3 - Value: 3310
Name: #text - Type: 3 - Value: GF768
Name: #text - Type: 3 - Value: Skeleton
Name: #text - Type: 3 - Value: Earl
这证明DOMElement 包含它的值,因为DOMText 和nodeValue 只是直接返回DOMText 的内容。
更多关于 nodeValue
事实上,nodeValue 足够聪明,可以连接任何DOMText 子项的内容:
$dom = new DOMDocument;
$dom->loadXML('<root><p>Hello <em>World</em>!!!</p></root>');
$node = $dom->documentElement->firstChild; // p
printf(
"Name: %s - Type: %s - Value: %s\n",
$node->nodeName,
$node->nodeType,
$node->nodeValue
);
会输出
Name: p - Type: 1 - Value: Hello World!!!
虽然这些确实是
DOMText "Hello"
DOMElement em with DOMText "World"
DOMText "!!!"
使用 XML DOM 打印 XML 文件的内容
要最终回答您的问题,请查看第一个测试代码。你需要的一切都在里面。当然,现在你也得到了很好的其他答案。