XPath根据属性值定位元素?

时间:2015-09-18 18:42:03

标签: php xml xpath

我正在尝试搜索我创建的XML文档,但我似乎无法让它正常工作。这是我的XML文档......

<?xml version="1.0" encoding="UTF-8"?>
<states>
<repstate location="AL">
    <compName>Test Company</compName>
    <name>Chris Brown</name>
    <address>123 Main St</address>
    <city>Anytown</city>
    <state>CT</state>
    <phone>203-123-4567</phone>
    <fax>203-456-7890</fax>
    <email>info@email.com</email>
    <website>www.testing.com</website>
    <serviceArea>All of Alabama</serviceArea>
</repstate>
<repstate location="AK">
    <compName>Test Company</compName>
    <name>Chris Brown</name>
    <address>123 Main St</address>
    <city>Anytown</city>
    <state>CT</state>
    <phone>203-123-4567</phone>
    <fax>203-456-7890</fax>
    <email>info@email.com</email>
    <website>www.testing.com</website>
    <serviceArea>All of Alabama</serviceArea>
</repstate>
</states>

这是我正在努力工作的代码片段......

        <?php 
            $xml = simplexml_load_file('../../usa.xml');
            $found = $xml->xpath("//@location='AK'");
            echo $found->state;
        ?>  

它似乎没有正常工作。

我正在尝试加载该节点中的信息。所以compName,名称,地址,城市,州,电话,传真,电子邮件,网站和serviceArea。我认为让“状态”工作很容易,但似乎没有输出。我做错了什么?

4 个答案:

答案 0 :(得分:1)

我对此并非100%肯定,但在c#中xPath将是:
// repstate [@location =&#39; AK&#39;]
所以你可以试试(由于我没有足够高的声誉,我无法将其作为评论:))

答案 1 :(得分:1)

您还没有说过您希望XPath表达式做什么。你的表达式是有效的,它将返回一个布尔值,如果在文档中的任何地方有@location属性等于“AK”,则该布尔值为真。

如果要查找@location属性等于“AK”的元素,请使用//*[@location='AK']

答案 2 :(得分:1)

除了xpath - 表达式本身,xpath还会向<{1}}返回 array SimpleXML个元素,所以...

$found

或 - 使用PHP&gt; = 5.4 - 您可以像这样取消引用数组:

echo $found[0]->state;

在此处查看:https://eval.in/435965

答案 3 :(得分:1)

正如 Micheal Kay his answer中概述的那样,xpath表达式是有效的。他不知道的是,对于SimpleXML,这不会导致空洞的结果。

因此,当您尝试从空数组中读取字段时,会看到致命错误。您的代码与此类似:

$found = array();
echo $found->state;

回显一个空字符串(由表达式给出的NULL值创建)和一个通知:

  

注意:尝试在...中获取非对象的属性

如果您还没有看到此通知,那么您在开发系统中启用错误消息至关重要,请参阅 How to get useful error messages in PHP?

正如您所看到的,它工作正常,它不能提供您所期望的。为了让自己以更高效的方式继续下去,如果你愿意分享你所期望的那样,那将会很棒。

或换句话说:正如其他人也回答的那样,你需要决定你要找的是什么。

从输出代码:

echo $found->state;

我说您正在寻找以下XML元素:

...
<repstate location="AK">
    <compName>Test Company</compName>
    <name>Chris Brown</name>
    <address>123 Main St</address>
    <city>Anytown</city>
    <state>CT</state>
    ...

以下是SimpleXML Xpath的工作原理:

  1. 您只能查询节点列表
  2. 支持的唯一节点是元素和属性
  3. 列表始终为数组类型
  4. 数组始终为零索引
  5. 数组中的每个条目 - 如果数组不为空 - 的类型为 SimpleXMLElement
  6. 因此,在您的情况下,如果我对要查询的元素的假设是正确的,则需要返回单个元素节点的state子元素的节点值。然后根据PHP代码:

    $list = $xml->xpath("//repstate[@location = 'AK']");
    list($repstate) = $list + array(null);
    $state = $repstate ? $repstate->state : '- no such location -';
    
    echo $state;
    

    然后使用XML输出:

      

    CT

    甚至更短:

    $list = $xml->xpath("//repstate[@location = 'AK']/state");
    list($state) = $list + array('- no such location -');
    
    echo $state;
    

    我希望这个更广泛的解释对你有所帮助。你的原始表达不起作用的原因是它已经违反了第一点:

    1. 您只能查询节点列表
    2. 因为您的xpath查询表示布尔表达式而不是节点列表。另外,SimpleXMLElement xpath中的这样一个列表需要你有一个元素或属性,而不是一个布尔表达式。