【问题标题】:Combining two Xpaths into one loop?将两个 Xpath 组合成一个循环?
【发布时间】:2013-10-03 21:00:14
【问题描述】:

我正在使用 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 信息组合在一起,而不是像在当前代码中那样让它们单独显示。

【问题讨论】:

    标签: php xml xpath domdocument


    【解决方案1】:

    这在一定程度上取决于您要达到的目标。您可以使用 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 查询应用到另一个的所有节点上,但我现在找不到。

    【讨论】:

    • 谢谢,非常感谢看到两种方法来完成我的需要。
    【解决方案2】:

    使用$xpath-&gt;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 一起显示而不是单独显示:

    【讨论】:

    • 如果您使用评估并且只处理结果的一个元素来获取它的节点值,请改为编写string() 表达式:$xpath-&gt;evaluate("string(MITS:MarketingName)", $unit) - 这已经返回一个字符串。
    • @hakre,很好的建议。更新。谢谢!
    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 2016-07-10
      • 2021-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多