使用XML DOM打印XML文件的内容

Sla*_*sic 4 php xml dom

我有一个简单的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>
Run Code Online (Sandbox Code Playgroud)

我需要使用XML DOM打印此文件的内容,它需要像这样构造:

"model: Easy DB
proizvodjac: Alcatel
cena: 25"
Run Code Online (Sandbox Code Playgroud)

对于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 />";
    }
?>
Run Code Online (Sandbox Code Playgroud)

谢谢

Gor*_*don 6

对奇怪的#text字符串的解释

奇怪的#text字符串不是蓝色的,而是实际的文本节点.当您使用DOM任何空格加载带格式的XML文档时,例如缩进,换行符和节点值将DOMText默认为DOM的一部分,例如

<cellphones>\n\t<telefon>\n\t\t<model>Easy DB…
E           T   E        T     E      T      
Run Code Online (Sandbox Code Playgroud)

其中E是a DOMElement而T是a DOMText.

要解决这个问题,请加载文档,如下所示:

$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->load('file.xml');
Run Code Online (Sandbox Code Playgroud)

然后您的文档结构如下

<cellphones><telefon><model>Easy DB…
E           E        E      T
Run Code Online (Sandbox Code Playgroud)

请注意,表示a值的各个节点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)
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码遍历给定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++
…
Run Code Online (Sandbox Code Playgroud)

我对该值进行了urlencoding的原因是为了表明实际上存在DOMText包含缩进和行间断的节点DOMDocument.%0A是一个换行符,而每个+都是一个空格.

当您将其与XML进行比较时,您将看到在每个<telefon>元素之后有一个换行符后跟四个空格,直到<model>元素开始.同样,在收盘<cena>和开盘之间只有一个换行符和两个空格<telefon>.

这些节点的给定类型是3,根据预定义常量列表,它是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
…
Run Code Online (Sandbox Code Playgroud)

如您所见,不再有#text节点,而只有类型1节点,这意味着XML_ELEMENT_NODE,例如DOMElement.

DOMElements包含DOMText节点

在开头我说过,值DOMElements也是DOMText实例.但在上面的输出中,它们无处可见.那是因为我们正在访问nodeValue属性,该属性返回DOMTextas字符串的值.我们可以证明价值很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)
    );
}
Run Code Online (Sandbox Code Playgroud)

将输出

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
Run Code Online (Sandbox Code Playgroud)

这证明了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
);
Run Code Online (Sandbox Code Playgroud)

将输出

Name: p - Type: 1 - Value: Hello World!!!
Run Code Online (Sandbox Code Playgroud)

虽然这些是真正的综合价值

DOMText "Hello"
DOMElement em with DOMText "World"
DOMText "!!!"
Run Code Online (Sandbox Code Playgroud)

使用XML DOM打印XML文件的内容

要最终回答您的问题,请查看第一个测试代码.你需要的一切都在那里.当然,到目前为止,你也得到了很好的其他答案.