简单的XML元素:抓住<link rel =“alternate”/>节点内的href

时间:2016-07-11 16:50:06

标签: php xml simplexml

我正在尝试解析xml文件中的不同链接。我阅读了文档以及我发现的有关解析xml文件的每篇文章,但我没有找到像我想要的那样访问节点的方法。例如:

<link rel="self" type="text/html" title="title0" length="8359" href="http://example0.com"/>
<link rel="alternate" type="text/html" title="title1" length="8359" href="http://example3.com"/>
<link rel="related" type="text/html" title="title2" length="8359" href="http://example4.com"/>
<link rel="related" type="text/html" title="title3" length="8359" href="http://example4.com"/>
<link rel="related" type="text/html" title="title4" length="8359" href="http://example5.com"/>
<link rel="related" type="text/html" title="title5" length="8359" href="http://example5.com"/>

我如何访问:

  1. 具有rel =&#34; self&#34;的链接的href。 (return String)。
  2. 具有rel =&#34; alternate&#34;的链接的href。 (return String)。
  3. 具有rel =&#34;相关&#34;的链接的hrefs (返回数组)。
  4. 使用SimpleXML:

    $xml=simplexml_load_file('url_to_xml') or die('Error: Cannot create object');
    

    ...

6 个答案:

答案 0 :(得分:4)

您通常希望使用XPath或类似的东西来解析XML文档。 SimpleXML支持它。例如:

<?php
$string = <<<XML
<div>
  <link rel="self" type="text/html" title="title0" length="8359" href="http://example0.com"/>
  <link rel="alternate" type="text/html" title="title1" length="8359" href="http://example3.com"/>
  <link rel="related" type="text/html" title="title2" length="8359" href="http://example4.com"/>
  <link rel="related" type="text/html" title="title3" length="8359" href="http://example4.com"/>
  <link rel="related" type="text/html" title="title4" length="8359" href="http://example5.com"/>
  <link rel="related" type="text/html" title="title5" length="8359" href="http://example5.com"/>
</div>
XML;
$xml = new SimpleXMLElement($string);
foreach(['self', 'alternate', 'related', 'dne'] as $rel) {
  $val = @$xml->xpath("//link[@rel='$rel']/@href");
  $val = $val ? array_map(function($n) { return (string)$n; }, $val) : [];
  $val = count($val) == 1 ? $val[0] : $val;
  var_dump($val);
}

答案 1 :(得分:1)

如果您不习惯使用xpath,那么您可以像访问对象一样访问link元素:

    <?php
    $string = <<<XML
    <div>
      <link rel="self" type="text/html" title="title0" length="8359" href="http://example0.com"/>
      <link rel="alternate" type="text/html" title="title1" length="8359" href="http://example3.com"/>
      <link rel="related" type="text/html" title="title2" length="8359" href="http://example4.com"/>
      <link rel="related" type="text/html" title="title3" length="8359" href="http://example4.com"/>
      <link rel="related" type="text/html" title="title4" length="8359" href="http://example5.com"/>
      <link rel="related" type="text/html" title="title5" length="8359" href="http://example5.com"/>
    </div>
    XML;

    $xml = new SimpleXMLElement($string);

    $related = [];

    foreach($xml->link as $link) {

        switch($link['rel']){
            case 'self':
                $self = $link['href'];
                break;
            case 'alternate':
                $alternate = $link['href'];
                break;
            case 'related':
                array_push($related, $link['href']);
                break;
        }

    }

    print $self;
    // outputs : http://example0.com

    print $alternate;
    // outputs : http://example3.com

    print_r($related);
    /* outputs : Array
(
    [0] => SimpleXMLElement Object
        (
            [0] => http://example4.com
        )

    [1] => SimpleXMLElement Object
        (
            [0] => http://example4.com
        )

    [2] => SimpleXMLElement Object
        (
            [0] => http://example5.com
        )

    [3] => SimpleXMLElement Object
        (
            [0] => http://example5.com
        )

)
*/

如果你不喜欢switch语句,你可以使用&#39;如果&#39;而是条件语句:

foreach($xml->link as $link) {
    if($link['rel'] == 'self'){
       $self = $link['href'];
    }
    if($link['rel'] == 'alternate'){
       $alternate = $link['href'];
    }
    if($link['rel'] == 'related'){
        array_push($related, $link['href']);
    }
}

答案 2 :(得分:1)

问题一般可以说是&#34;如何根据其他属性之一的值来访问XML元素的属性&#34;。有两种基本方法:迭代所有候选元素,并检查属性值;或使用XPath搜索文档。

找到匹配的元素后,您需要访问该属性,在SimpleXML中,这意味着知道两种语法:

  • $something['bar']从表示元素的对象(例如<foo>)到表示其属性之一的对象(例如bar="..."
  • (string)$something将变量强制转换为字符串,对于SimpleXML,它为您提供元素或属性的完整字符串内容

使用SimpleXML使用迭代非常简单,因为您可以使用foreachif,这应该是一种非常直观的方式。假设$xml已经指向<link>元素的父元素:

foreach ( $xml->link as $link ) {
    if ( $link['rel'] == 'self' ) {
        // Found <link rel="self">
        // assign to variable, return from function, etc
        // To access the attribute, we use $link['href']
        // To get the text content of the selected node,
        //   we cast to string with (string)$link['href']
        $self_link = (string)$link['href'];
    }
}

使用XPath,您可以使用紧凑表达式在整个文档中搜索具有特定名称和属性值的元素:

  • //foo在文档的任何位置搜索名为<foo>的所有元素
  • [bar]表示&#34;其子元素名为&#34; bar&#34;
  • [@bar]代表&#34;其中有一个名为&#34; bar&#34;的属性,这就是我们想要的内容
  • [@bar="baz"]表示&#34; bar&#34;的价值属性必须是&#34; baz&#34;

所以在我们的案例中,//link[@rel="self"]

在SimpleXML中,您可以在任何节点上调用->xpath(),并获取零个或多个对象的数组。然后,您将要遍历这些,提取适当的值:

$xpath_results = $xml->xpath('//link[@rel="self"]');
foreach ( $xpath_results as $node ) {
     // Again, we have a SimpleXMLElement object, and want 
     //    the string content of the 'href' attribute:
     $self_link = (string)$node['href'];
}

答案 3 :(得分:0)

你可以使用if / switch语句,例如。

foreach($xml->getElementsByTagName('link') as $tag) {
   switch($tag->getAttribute('rel')) {
      case 'self':
         $href_of_self = $tag->getAttribute('href');
         break;
      case 'related':
         ...
   }
}

通过标记获取元素并获取元素的属性可以通过以下方法完成: http://php.net/manual/en/domdocument.getelementsbytagname.php http://php.net/manual/en/domelement.getattribute.php

答案 4 :(得分:0)

您可以使用http://sabre.io/xml将其描述为“您可能不讨厌的PHP XML库”。注意函数parseCurrentElement()https://github.com/fruux/sabre-xml/blob/master/lib/Reader.php

您可以创建自定义阅读器

class CustomXmlReader extends \Sabre\Xml\Reader {}
class CustomXmlService extends \Sabre\Xml\Service {}

答案 5 :(得分:-3)

如果您正在处理大型文件,可能需要将文件拆分为行,然后使用preg_match处理每一行。如果您的XML文件具有类似的结构,这显然效果最佳。