我有一个简单的XML文档:
<?xml version="1.0"?>
<cellphones>
<telefon>
<model>Easy DB</model>
<proizvodjac>Alcatel</proizvodjac>
<cena>25</cena>
</telefon>
<telefon>
<model>3310</model>
<proizvodjac>Nokia</proizvodjac>
<cena>30</cena>
</telefon>
<telefon>
<model>GF768</model>
<proizvodjac>Ericsson</proizvodjac>
<cena>15</cena>
</telefon>
<telefon>
<model>Skeleton</model>
<proizvodjac>Panasonic</proizvodjac>
<cena>45</cena>
</telefon>
<telefon>
<model>Earl</model>
<proizvodjac>Sharp</proizvodjac>
<cena>60</cena>
</telefon>
</cellphones>
我需要使用XML DOM打印此文件的内容,并且需要按以下方式构建:
"model: Easy DB
proizvodjac: Alcatel
cena: 25"
表示XML中的每个节点。
使用XML DOM即可完成。那就是问题所在。我可以通常,简单的方式做到这一点。但是这个让我烦恼,因为我似乎无法在互联网上找到任何解决方案。
这是我可以做的,但我需要访问内部节点(子节点)并获取节点值。我还想摆脱一些奇怪的字符串“#text”,它出现了。
<?php
//kreira se DOMDocument objekat
$xmlDoc = new DOMDocument();
//u xml objekat se ucitava xml fajl
$xmlDoc->load("poruke.xml");
//dodeljuje se promenljivoj koreni element
$x = $xmlDoc->documentElement;
//prolazi se kroz petlju tako sto se ispisuje informacija o podelementima
foreach ($x->childNodes AS $item){
print $item->nodeName . " = " . $item->nodeValue . "<br />";
}
?>
由于
答案 0 :(得分:6)
对奇怪的#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++
…
我对该值进行了编码的原因是为了显示实际上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节点,而只有类型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文件的内容
要最后回答您的问题,请查看第一个测试代码。你需要的一切都在那里。当然,到目前为止,你也得到了很好的其他答案。
答案 1 :(得分:2)
在我看来,你想要这样的东西:
<?php
$dom = new DOMDocument();
$dom->load("poruke.xml");
$telefon = $dom->getElementsByTagName('telefon');
foreach ($telefon as $t) {
print "model: " . $t->childNodes->item(0)->nodeValue . "\n" .
"proizvodjac: " . $t->childNodes->item(1)->nodeValue . "\n" .
"cena: " . $t->childNodes->item(2)->nodeValue;
}
这可能不是您在格式化方面所需要的,但它应该向您显示您需要做的事情。
答案 2 :(得分:2)
这是经过试验和测试的解决方案。
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load("mobiles.xml");
$x = $xmlDoc->documentElement;
$telefons = $x->getElementsByTagName( "telefon" );
foreach( $telefons as $telefon )
{
$model = $telefon->getElementsByTagName( "model" );
$proiz = $telefon->getElementsByTagName( "proizvodjac" );
$cena = $telefon->getElementsByTagName( "cena" );
echo $model->item(0)->nodeName .': '. $model->item(0)->nodeValue.' <br> '.$proiz->item(0)->nodeName .':'.$proiz->item(0)->nodeValue.'<br> '.$cena->item(0)->nodeName.':'.$cena->item(0)->nodeValue.' <br><br>';
}
?>
答案 3 :(得分:2)
试一试
$xmlDoc = new DOMDocument();
$dom->load("poruke.xml");
// Load the DomDoc into an Xpath object, you can then query it
$xpath = new DOMXpath($xmlDoc);
// Find all telefon elements
$result = $xpath->query("//telefon");
// For each telefon item found
foreach ($result AS $item){
// For each child node of the telefon element print the nodeName and nodeValue
foreach($item->childNodes as $node){
echo $node->nodeName . " = " . $node->nodeValue . " <br />";
}
}
答案 4 :(得分:0)
找到一种非常简单的方法:
$xml = $domElement->ownerDocument->saveXML($domElement);
或者您已将文档保存在变量中。
$xml = $document->saveXML($domElement);