通过搜索其他值来提取XML值

时间:2017-11-08 15:22:37

标签: php xml xpath

我确定我在语法上遇到了一些简单的错误,但我已经尝试了几种不同的迭代和变体。无法到达那里!

我正在使用的XML数据如下所示:

<HybridSchedule>
    <matchNumber>1</matchNumber>
    <scoreBlueFinal>260</scoreBlueFinal>
    <scoreRedFinal>135</scoreRedFinal>
    <startTime>2017-03-25T10:30:00</startTime>
    <Teams>
        <Team>
            <station>Red1</station>
            <teamNumber>6514</teamNumber>
        </Team>
        <Team>
            <station>Red2</station>
            <teamNumber>1285</teamNumber>
        </Team>
    </Teams>
</HybridSchedule>

我尝试做的是根据电台

的值提取 teamNumber

我尝试过的其他许多变体包括:

$red1res = $HybridSchedule->xpath("//Teams/Team/station[.='Red1']/parent::*");
$red1 = $red1res[0]->teamNumber;

上面的代码返回空白,我已根据我在不同网站上找到的代码尝试了十几种变体,但我显然遗漏了一些东西。根据提供的样本数据,$ red1的值应为6514。

根据目前为止提供的反馈,这里是具有更大背景的新代码:

foreach ($xml->Schedule->children() as $HybridSchedule) {

        // Collect the data for the table
        $match = $HybridSchedule->matchNumber;
        $schedelements = explode("T", $HybridSchedule->startTime);
        $schedtime = substr($schedelements[1], 0, 5);
        $scorebluefinal = $HybridSchedule->scoreBlueFinal;
        $scoreredfinal = $HybridSchedule->scoreRedFinal;
        $Teams = $HybridSchedule->Teams;

        $blue1res = $Teams->xpath("/Team[station='Blue1']/teamNumber/text()");
        $blue1 = $blue1res[0];
}

xpath现在正在运行,但是数组显示的是$ xml中的所有条目,而不仅仅是来自$ HybridSchedule的条目。

3 个答案:

答案 0 :(得分:1)

您将Xpath的结果分配到$red1res但是从$blue1res读取值 - 这是两个不同的变量。

无论如何,如果你以稍微不同的方式看待它,你的X路可以简化:

  1. 任何子元素Team中的任何Teams子元素...
    Teams/Team
  2. station文字内容为Red1 ...
    Teams/Team[station='Red1']
  3. teamNumber孩子......
    Teams/Team[station='Red1']/teamNumber
  4. []中的过滤条件可能很复杂。这样只返回匹配的Team,所以这里不需要重新启动。

    使用/启动表达式意味着它将位于文档的上下文中,两个//表示您获取任何后代。如果您只是从标记名称开始,它会查看子节点。要在仍然使用上下文的同时获取后代,您必须使用.//.表示当前节点,并避免使用/启动位置路径。)

    此外,Xpath允许类型转换,但这只适用于DOMXpath::evaluate()。 (不是SimpleXMLElement::xpath()。)

    1. 将结果转换为字符串
      string(Teams/Team[station='Red1']/teamNumber)
    2. 您已经知道如何将Xpath与SimpleXML一起使用,所以这里有一个DOM示例:

      $document = new DOMDocument();
      $document->loadXml($xml);
      $xpath = new DOMXpath($document);
      
      $schedule = $document->documentElement; 
      
      var_dump(
        $xpath->evaluate('string(Teams/Team[station="Red1"]/teamNumber)', $schedule)
      );
      

      输出:

      string(4) "6514"
      

      SimpleXMLElement::xpath()DOMXpath::evaluate()之间的差异是SimpleXMLElement表示元素节点,此元素节点用作表达式的上下文。 DOMXpath实例仅连接到文档,因此您必须提供上下文作为方法调用的参数。

答案 1 :(得分:0)

你的XPath几乎就在那里......

//Teams/Team/station[.='Red1']/parent::*/teamNumber/text()

有时这是尝试它的情况,我使用类似http://www.xpathtester.com/xpath的东西,它允许你调整XPath,直到你得到你的信息。

答案 2 :(得分:-1)

我会改用SimpleXML。在我看来,它是一个更干净的API,正如@Jesse指出的那样,它得到了官方的支持。

// If you have the XML as a string in a variable
$xml = simplexml_load_string($xmlString);

// If you prefer the OOP style
$xml = new SimpleXMLElement($xmlString);

// If you're loading it from a file
$xml = simplexml_load_file('/path/to/file');

$teamNumber = null;

foreach ($xml->Teams->Team as $team) {
    if ($team->station == 'Red1') {
        // We need to cast it as an int, or we're going to end up
        // with a "SimpleXMLElement"-object.
        $teamNumber = (int) $team->teamNumber;

        // We found our item, let's stop iterating
        break;
    }
}

演示:https://3v4l.org/dt2Tr