使用SimpleXML和XPath迭代XML,结果的顺序错误

时间:2015-07-29 19:52:39

标签: php xml xpath simplexml

my variables.php

$xmlFile = 'xml.xml';
$xmlFileLoad = simplexml_load_file($xmlFile);
$xmlFileLoad->registerXPathNamespace("oi", "http://www.openimmo.de");
$immobilie = $xmlFileLoad->xpath('//oi:immobilie');

$zustand_angaben_letztemodernisierung = $xmlFileLoad->xpath('/oi:openimmo/oi:immobilie/oi:zustand_angaben/oi:letztemodernisierung');
$zustand_angaben_zustand = $xmlFileLoad->xpath('/oi:openimmo/oi:immobilie/oi:zustand_angaben/oi:zustand/@zustand_art');
$zustand_angaben_alter = $xmlFileLoad->xpath('/oi:openimmo/oi:immobilie/oi:zustand_angaben/oi:alter/@alter_attr');
$zustand_angaben_erschliessung = $xmlFileLoad->xpath('/oi:openimmo/oi:immobilie/oi:zustand_angaben/oi:erschliessung/@erschl_attr');
$zustand_angaben_altlasten = $xmlFileLoad->xpath('/oi:openimmo/oi:immobilie/oi:zustand_angaben/oi:altlasten');
$zustand_angaben_baujahr = $xmlFileLoad->xpath('/oi:openimmo/oi:immobilie/oi:zustand_angaben/oi:baujahr');

xml文件(缩短版)

<?xml version="1.0" encoding="utf-8"?>
<openimmo xmlns="http://www.openimmo.de"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.openimmo.de openimmo.xsd">
    <immobilie>
        <zustand_angaben>
            <altlasten>keine</altlasten>
        </zustand_angaben>
    </immobilie>
    <immobilie>
        <zustand_angaben>
            <altlasten>keine</altlasten>
        </zustand_angaben>
    </immobilie>
    <immobilie>
        <zustand_angaben>
            <altlasten>keine</altlasten>
        </zustand_angaben>
    </immobilie>
    <immobilie>
        <zustand_angaben>
            <baujahr>ca. 1900</baujahr>
            <altlasten>nein</altlasten>
        </zustand_angaben>
    </immobilie>
    <immobilie>
        <zustand_angaben>
            <baujahr>ca. 1989</baujahr>
            <zustand zustand_art="ERSTBEZUG" />
            <alter alter_attr="ALTBAU" />
            <altlasten>keine</altlasten>
        </zustand_angaben>
    </immobilie>
</openimmo>

我的show.php

<?php
    include("variables.php");

    $i = 0;
    foreach ($immobilie as $immo) {

        echo "Immobilie $i<br />";
        if(isset($zustand_angaben_zustand[$i])) {
            echo $zustand_angaben_zustand[$i] . "</br>";
        }

        if(isset($zustand_angaben_alter[$i])) {
            echo $zustand_angaben_alter[$i] . "</br>";
        }

        if(isset($zustand_angaben_erschliessung[$i])) {
            echo $zustand_angaben_erschliessung[$i] . "</br>";
        }

        if(isset($zustand_angaben_altlasten[$i])) {
            echo $zustand_angaben_altlasten[$i] . "</br>";
        }

        if(isset($zustand_angaben_baujahr[$i])) {
            echo $zustand_angaben_baujahr[$i] . "</br>";
        }   
        echo "<br /><br />";
        $i++;
    }
?>

当我执行代码时,结果将是以下

Immobilie 0
ERSTBEZUG
ALTBAU
keine
5
A
5
A++
ca. 1900

Immobilie 1
keine

ca. 1989

Immobilie 2
keine

Immobilie 3
nein

Immobilie 4
keine

但我希望它按照xml中的顺序,所以Immobilie 0只有keine,Immobilie 1和2,第三个1900和nein,最后但并非最不重要的Immobilie 4具有xml中的所有属性...

我做错了什么?

2 个答案:

答案 0 :(得分:0)

使用相对于当前immobilie元素的XPath表达式:

$i = 0;
foreach ($immobilie as $immo) {
    $immo->registerXPathNamespace("oi", "http://www.openimmo.de");
    $zustand_angaben_letztemodernisierung = $immo->xpath('./oi:zustand_angaben/oi:letztemodernisierung');
    $zustand_angaben_zustand = $immo->xpath('./oi:zustand_angaben/oi:zustand/@zustand_art');
    $zustand_angaben_alter = $immo->xpath('./oi:zustand_angaben/oi:alter/@alter_attr');
    $zustand_angaben_erschliessung = $immo->xpath('./oi:zustand_angaben/oi:erschliessung/@erschl_attr');
    $zustand_angaben_altlasten = $immo->xpath('./oi:zustand_angaben/oi:altlasten');
    $zustand_angaben_baujahr = $immo->xpath('./oi:zustand_angaben/oi:baujahr');

    echo "Immobilie $i<br />";
    if(isset($zustand_angaben_zustand[0])) {
        echo $zustand_angaben_zustand[0] . "</br>";
    }

    if(isset($zustand_angaben_alter[0])) {
        echo $zustand_angaben_alter[0] . "</br>";
    }

    if(isset($zustand_angaben_erschliessung[0])) {
        echo $zustand_angaben_erschliessung[0] . "</br>";
    }

    if(isset($zustand_angaben_altlasten[0])) {
        echo $zustand_angaben_altlasten[0] . "</br>";
    }

    if(isset($zustand_angaben_baujahr[0])) {
        echo $zustand_angaben_baujahr[0] . "</br>";
    }   
    echo "<br /><br />";
    $i++;
}

<强> eval.in demo

答案 1 :(得分:0)

当你并行运行xpath查询时,它们的所有顺序都是彼此相邻的。

对于您的具体实例,您还不需要xpath,该文档看起来像 SimpleXMLElement 的完美工作,您可以直接从中检索数据。

如果你对你感兴趣的对象(这里很可能每个 immobilie 元素)进行预测,然后提取数据(过滤掉未设置的元素),它可以类似于以下示例:

$xml = simplexml_load_string($string);

foreach ($xml->immobilie as $immobilie) {
    $angaben = $immobilie->zustand_angaben;

    $data = [
        'letzte_modernisierung' => $angaben->letztemodernisierung,
        'zustand_art'           => $angaben->zustand['zustand_art'],
        'alter'                 => $angaben->alter['alter_attr'],
        'erschliessung'         => $angaben->erschliessung['erschl_attr'],
        'altlasten'             => $angaben->altlasten,
        'baujahr'               => $angaben->baujahr,
    ];

    echo " * Immobilie:\n";
    foreach(array_filter($data) as $label => $wert) {
        echo "   - $label: $wert\n";
    }
}

输出(也是:online-demo):

 * Immobilie:
   - altlasten: keine
 * Immobilie:
   - altlasten: keine
 * Immobilie:
   - altlasten: keine
 * Immobilie:
   - altlasten: nein
   - baujahr: ca. 1900
 * Immobilie:
   - zustand_art: ERSTBEZUG
   - alter: ALTBAU
   - altlasten: keine
   - baujahr: ca. 1989

Xpath一点都不差,对于像你这样的场景,我建议你使用 DOMDocument 而不是 SimpleXMLElement 作为它由于评估方法 DOMXpath 具有Xpath,因此使用Xpath更灵活。

在任何情况下,您都可以继续阅读此问题,该问题显示一个 DOMDocument 和一个 SimpleXMLElement 解决方案,用于从XML文档中检索基于Xpath的数据: