将两个Xpath组合成一个循环?

时间:2013-09-27 14:08:41

标签: php xml xpath domdocument

我正在使用xpath从文档中获取信息,唯一的问题是我无法将它们组合成1 for循环,因此信息在页面上正确显示。我的代码是:

<?php

$doc = new DOMDocument;
$doc->preserveWhiteSpace = FALSE;
$doc->load('http://mdoerrdev.com/xml/updates-mits.xml');

$xpath = new DOMXPath($doc);
$xpath->registerNamespace('MITS', "http://www.mitsproject.org/namespace");

$unitName  = $xpath->evaluate("//ILS_Unit[@FloorplanID='550584']/Unit/MITS:MarketingName");
$unitPrice = $xpath->evaluate("//ILS_Unit[@FloorplanID='550584']/Unit/MITS:Information/MITS:MarketRent");

?>

    <div class="unit-name">
        <?php
        foreach ($unitName as $un) {
            echo $un->nodeValue . "\n";
        }
        ?>
    </div>

    <div class="floor-plan-box fpb-one-bedroom cleafix"> <?php
        foreach ($unitPrice as $up) {
            echo $up->nodeValue . "\n";

            ?><img src='<?php bloginfo('stylesheet_directory'); ?>/img/floorplans/<?php echo "550584" ?>.jpg' /> <?php
        };
        ?>
    </div>

(来自:http://pastie.org/8360106

我需要将MarketRent和MarketingName信息组合在一起,而不是像在当前代码中那样单独显示它们。

3 个答案:

答案 0 :(得分:3)

这取决于你想要实现的目标。您可以使用 Union 运算符(管道|)组合两个xpath表达式:

$unitName = $xpath->evaluate("
(
    //ILS_Unit[@FloorplanID='550584']/Unit/MITS:MarketingName
    |//ILS_Unit[@FloorplanID='550584']/Unit/MITS:Information/MITS:MarketRent
)
");

然后按文档顺序返回所有已评估的节点:

<div class="unit-name">
        1265.0000
C-304
1265.0000
C-308
1255.0000
C-204
1255.0000
C-208
1230.0000
C-102
1230.0000
C-103
    </div>

这可能不是你想要的。相反,您希望同时评估两个结果,这可以使用MultipleIterator

来实现
$unitName  = $xpath->evaluate("//ILS_Unit[@FloorplanID='550584']/Unit/MITS:MarketingName");
$unitPrice = $xpath->evaluate("//ILS_Unit[@FloorplanID='550584']/Unit/MITS:Information/MITS:MarketRent");

$it = new MultipleIterator();
$it->attachIterator(new IteratorIterator($unitName));
$it->attachIterator(new IteratorIterator($unitPrice));

foreach($it as $value) {
    list($name, $price) = $value;
    echo " * ", $name->nodeValue, " ", $price->nodeValue, "\n";
}

输出:

 * C-304 1265.0000
 * C-308 1265.0000
 * C-204 1255.0000
 * C-208 1255.0000
 * C-102 1230.0000
 * C-103 1230.0000

这可能是您正在寻找的更多内容。另外,对于你所做的事情,SimpleXMLElement 可能更容易使用,因为它已经允许在字符串上下文中输出节点。

此外,还有另一个概念可以将浅层对象直接映射到基础XML文档,这里概述了它:

这是一个非常有趣的概念。 IIRC我写了类似的东西,比如将一个xpath查询应用到另一个节点的所有节点上,但我现在还没找到它。

答案 1 :(得分:3)

我无法抗拒另外尝试在某些XML源上应用模型。我为这个答案选择了SimpleXMLElement。它只是透明的,并且几乎只对xpath表达式有影响。应该可以将同一个界面翻译为DOMDocument

$unitPrototype = new XPrototype(
    "//ILS_Unit[@FloorplanID='550584']/Unit",
    [
        'name'  => 'MITS:MarketingName',
        'price' => 'MITS:Information/MITS:MarketRent'
    ]
);

$units = new XList('http://mdoerrdev.com/xml/updates-mits.xml', $unitPrototype);

foreach ($units as $unit) {
    echo
    $unit->name, " ",
    $unit->price, "\n";
}

XPrototypeXList等已使用类型的来源位于Github:XObjects.php

答案 2 :(得分:2)

使用$xpath->evaluate() ...

的上下文节点参数

您的代码进行了这些调整:

<?php

$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->load('http://mdoerrdev.com/xml/updates-mits.xml');

$xpath = new DOMXPath($doc);
$xpath->registerNamespace('MITS', "http://www.mitsproject.org/namespace");

$units = $xpath->evaluate("//ILS_Unit[@FloorplanID='550584']/Unit");
echo "<table>";
echo "<tr><th>Marketing Name</th><th>Market Rent</th></tr>";
foreach($units as $unit)  {
  $marketingName = $xpath->evaluate("string(MITS:MarketingName)", $unit);
  $marketRent = $xpath->evaluate("string(MITS:Information/MITS:MarketRent)", $unit);
  echo "<tr>";
  echo "  <td>" . $marketingName . "</td>";
  echo "  <td>" . $marketRent . "</td>";
  echo "</tr>";
}
echo "</table>";
?>

根据您的请求,将MarketingName和MarketRent一起显示而不是单独显示,从而产生此输出:

enter image description here