SimpleXML 和 php - 获取包含与另一个节点匹配的文本的节点

Posted

技术标签:

【中文标题】SimpleXML 和 php - 获取包含与另一个节点匹配的文本的节点【英文标题】:SimpleXML and php - get a node that contains text that matches another node 【发布时间】:2014-06-21 21:05:29 【问题描述】:

如果该节点的内容与另一个节点(兄弟)匹配,我正在尝试显示该节点的文本内容。这是 XML:

<MemberId>
    <BillingInfo>
        <Details>
            <Line NUMBER="0">
                <ChargeDate>20140605</ChargeDate>
                <DueDate>20140605</DueDate>
                <TrackingNumber>PR DED</TrackingNumber>
                <Description>Account payroll deduction</Description>
                <RevCode>SJ1550</RevCode>
                <RevDesc>ACCOUNT PAYROLL DEDUCTION</RevDesc>
                <SalesAmount>-11.77</SalesAmount>
                <ServiceCharge>0.00</ServiceCharge>
                <GST>0.00</GST>
                <PST>0.00</PST>
                <Othertaxes>0.00</Othertaxes>
                <Total>-11.77</Total>
                <ChitCode>PR DED</ChitCode>
                <ChitDate>20140605</ChitDate>
            </Line>

            <Line NUMBER="1">
                <ChargeDate>20140605</ChargeDate>
                <DueDate>20140605</DueDate>
                <TrackingNumber>03128862</TrackingNumber>
                <Description>Mountain Mkt Sales</Description>
                <RevCode>SJ1553</RevCode>
                <RevDesc>MOUNTAIN MKT SALES</RevDesc>
                <SalesAmount>8.99</SalesAmount>
                <ServiceCharge>0.00</ServiceCharge>
                <GST>0.00</GST>
                <PST>0.61</PST>
                <Othertaxes>0.00</Othertaxes>
                <Total>9.60</Total>
                <ChitCode>03128862</ChitCode>
                <ChitDate>20140605</ChitDate>
            </Line>
        </Details>
    </BillingInfo>
    <Chits>
    <Chit>
    <Code>03128862</Code>
    <Body><![CDATA[
        Member#: 0ECHER
        Name: *******
        Area:  *********
        Server: JEANNEANE
        Chit#: 03128862
        Date:  June 5 2014
        ------- ------- ------- ------- -------
        1       MINGUA BEEF JER            8.99
        ------- ------- ------- ------- -------
        Sub-Total                          8.99


        TAX                                0.61
        ------- ------- ------- ------- -------
        Chit Total                         9.60



        MEMBER CHARGE                     -9.60
    ]]></Body>
    </Chit>
    </Chits>
</MemberId>

我成功地显示了每个 ChitCode 和 ChitDate,因为它们位于 Line[@number] 节点中。我想显示包含文本“Chit#: XXXXXX”的 Body 节点,其中 xxxxxx 匹配 Line->ChitCode。这是我的 php,它显示了正文,但它显示了所有行项目的第一个正文:

<?php 
    foreach($Chitquery as $Chit) 
    
        foreach($Linequery as $Line)
        
            echo "<label class='collapse' for='".$Line->ChitCode."-".$Line->ChitDate."'>".$Line->Description."</label>
            <input id='".$Line->ChitCode."-".$Line->ChitDate."' type='checkbox'>
            <div>"; 
            // Creates hide - show link for each Description item
            // Start getting the matching Chit Code from Chit/Body                          

            if ($Chit->Code = $Line->ChitCode)
            
                echo $Chit->Body."</div>";
            
            else
            
                echo " ".$Line->ChitCode."</div>";
             // End If
         //End  foreach Linequery
     // End foreach Chitquery
?>

这是回声 $Chit->Body。"";我需要帮助,我想显示包含 $Line->ChitCode 值的 Body。

哦,是的,由于“foreach”语句的放置不当,这些行重复得很奇怪! 帮助!提前致谢!

更新:我已经更改了我的 php 代码,现在我可以使用隐藏显示 div,没有重复,但我得到的是 'array' 而不是 $ChitBody。我无法弄清楚如何在 $ChitBody = $member->xpath('Chits/Chit/Body[text()="'.$Line->ChitCode.'" 中找到包含 $Line->ChitCode 的 Body 节点] ');

<?php 
                        foreach($Linequery as $Line)  
                        $ChitCode = $member->Chits->Chit->Code;
                        $ChitBody = $member->xpath('Chits/Chit/Body[text()="'.$Line->ChitCode.'"] ');
                        echo "<label class='collapse' for='".$Line->ChitCode."-".$Line->ChitDate."'>".$Line->Description."</label>
                         <input id='".$Line->ChitCode."-".$Line->ChitDate."' type='checkbox'>"; // Creates hide - show link for each Description item
                        // Start getting the matching Chit Code from Chit/Body                          
                            if ($ChitCode = $Line->ChitCode) 
                            echo "<div>Code: ".$ChitCode."<br>".$ChitBody."</div>";
                             else 
                            echo "<div>".$Line->ChitCode."</div>";
                             // End If
                         //End  foreachLinequery
                     ?>

【问题讨论】:

if 语句中有 $Chit->Code = $Line->ChitCode。尝试将其更改为 $Chit->Code == $Line->ChitCode. 【参考方案1】:

您很可能正在寻找 xpath 来查询您的文档。

例如遍历行 - 我不完全理解您为什么要这样做,但这是我理解的遍历行的方式(纯文本输出):

$xml = simplexml_load_string($buffer);

foreach ($xml->xpath('//Details/Line') as $line)

    printf("#%d: %s\n", $line['NUMBER'], $line->Description);            

给出:

#0: Account payroll deduction
#1: Mountain Mkt Sales

我想你知道这通常是如何工作的。因此,现在基于$line-&gt;ChitCode 获取信息,我认为这对您来说实际上是更有趣的部分。它也更好地说明了 xpath 的好处:

foreach ($xml->xpath('//Details/Line') as $line)

    printf("#%d: [%s] %s\n", $line['NUMBER'], $line->ChitCode, $line->Description);

    $query  = sprintf("//Chits/Chit[Code = '%s']/Body", $line->ChitCode);
    $result = $xml->xpath($query);

    if ($result) 
        $chit = $result[0];
        echo $chit;
     else 
        echo ' -- no chit found -- ';
    
    echo "\n";

这次查询包含查找数字的条件(如果你想保存,escape the string properly (more info)),它基本上创建了以下两个 xpath 查询:

//Chits/Chit[Code = 'PR DED']/Body

//Chits/Chit[Code = '03128862']/Body

我再次猜想你可以想象这些是什么意思。如果找到这样的&lt;Body&gt; 元素,上面的代码会输出它。结果是这样的:

#0: [PR DED] Account payroll deduction
 -- no chit found -- 
#1: [03128862] Mountain Mkt Sales

        Member#: 0ECHER
        Name: *******
        Area:  *********
        Server: JEANNEANE
        Chit#: 03128862
        Date:  June 5 2014
        ------- ------- ------- ------- -------
        1       MINGUA BEEF JER            8.99
        ------- ------- ------- ------- -------
        Sub-Total                          8.99


        TAX                                0.61
        ------- ------- ------- ------- -------
        Chit Total                         9.60



        MEMBER CHARGE                     -9.60

我希望这能让您有足够的洞察力来开始使用它。 xpath() is just a method on SimpleXMLElement 所以你也可以将它与我没有复制的代码结合起来,只是为了让示例更小(与我在这里使用纯文本输出的原因相同,与 html 相同,但会使示例膨胀)。


由 OP 添加:

效果很好!!

我已将您的代码调整为适用于此,并且效果很好:

foreach ($Linequery as $Line) 
    $LineChitCode = $Line->ChitCode;
    $ChitBody     = sprintf("//Chits/Chit[Code = '%s']/Body", $LineChitCode);
    $CBresult     = $member->xpath($ChitBody);
    echo "<label class='collapse' for='" . $Line->ChitCode . "-" . $Line->ChitDate . "'>" . $Line->Description . "</label>
                             <input id='" . $Line->ChitCode . "-" . $Line->ChitDate . "' type='checkbox'>"; // Creates hide - show link for each Description item
    // Start getting the matching Chit Code from Chit/Body                            
    if ($CBresult) 
        $chit = $CBresult[0];
        echo "<div>Code: " . $LineChitCode . "<br>" . $chit . "</div>";
     else 
        echo "<div>" . $Line->ChitCode . "</div>";
    

谢谢,你让我免于花 3 天时间来解决这个问题!

【讨论】:

@CharlieTrig:您也可以使用 xpath 查找兄弟姐妹,但这种方式更直接。仅供参考:)【参考方案2】:

你可以使用 if ($Chit->Code == $Line->ChitCode) 而不是 if ($Chit->Code = $Line->ChitCode)

【讨论】:

那行不通。仍然有重复,并且不显示与 $Line->ChitCode 的 Body 匹配

以上是关于SimpleXML 和 php - 获取包含与另一个节点匹配的文本的节点的主要内容,如果未能解决你的问题,请参考以下文章

PHP SimpleXML xpath:包含和定位

使用 SimpleXML 和 PHP 通过 https 获取 XML 内容的问题 [重复]

通过PHP和SimpleXML问题显示数据

PHP 5 SimpleXML 函数

PHP 5 SimpleXML 函数

如何使用simpleXML(php)通过xpath获取父节点