【问题标题】:How do I access this numeric element in a SimpleXML object?如何访问 SimpleXML 对象中的这个数字元素?
【发布时间】:2015-02-13 17:47:23
【问题描述】:

我正在从我们在 Web 应用程序中使用的数据源解析 XML,但在访问 XML 中特定部分的数据时遇到了一些问题。

首先,这是我尝试访问的print_r 的输出。

SimpleXMLElement Object
(
    [0] => 
This is the value I'm trying to get

)

然后,这是我要获取的 XML。

<entry>    
    <activity:object>
        <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
        <id>542</id>
        <title>
        Title string is a string
        </title>
        <content>
        This is the value I'm trying to get
        </content>
        <link rel="alternate" type="html" href="#"/>
        <link rel="via" type="text/html" href="#"/>
    </activity:object>
</entry>

内容元素是我所追求的。

当我使用$post-&gt;xpath('activity:object')[0]-&gt;content 访问它时,我最终得到了上面的内容。

我尝试使用$zero = 0;-&gt;content-&gt;{'0'} 来访问此元素,但每次我只返回一个空的SimpleXML 对象,如下所示。

SimpleXMLElement Object
(
)

还有其他我还没有找到的访问方法吗?

谢谢!

【问题讨论】:

    标签: php xml xpath simplexml


    【解决方案1】:

    xpath 返回一个simpleXMLElement 类型,该类型具有将其转换为字符串的函数。试试这个功能:

    http://php.net/manual/en/simplexmlelement.tostring.php

    【讨论】:

    • 不幸的是,我收到一条错误消息,提示我无法以非静态方式运行静态方法。我真的希望它会像这样简单!
    【解决方案2】:

    您应该可以直接访问它:

    $content = $post->xpath('//content');
    
    echo $content[0];
    

    使用 PHP 5.4 或更高版本,您或许可以这样做:

    $content = $post->xpath('//content')[0]; 
    

    或者,如果您将 XML 转换为字符串,如 @kkhugs 所说,您可以使用

    /**
     * substr_delimeters
     *
     * a quickly written, untested function to do some string manipulation for
     * not further dedicated and unspecified things, especially abused for use
     * with XML and from http://stackoverflow.com/a/27487534/367456
     *
     * @param string $string
     * @param string $delimeterLeft
     * @param string $delimeterRight
     *
     * @return bool|string
     */
    function substr_delimeters($string, $delimeterLeft, $delimeterRight)
    {
        if (empty($string) || empty($delimeterLeft) || empty($delimeterRight)) {
            return false;
        }
    
        $posLeft = stripos($string, $delimeterLeft);
        if ($posLeft === false) {
            return false;
        }
    
        $posLeft += strlen($delimeterLeft);
    
        $posRight = stripos($string, $delimeterRight, $posLeft + 1);
        if ($posRight === false) {
            return false;
        }
    
        return substr($string, $posLeft, $posRight - $posLeft);
    }
    
    $content = substr_delimeters($xmlString, "<content>", "</content>");
    

    【讨论】:

    • 不幸的是,这也不起作用。我也只是在那里取回一个空物体。我发布的内容实际上只是我较大的 XML 文件的一个 sn-p(太大,无法在此处发布)但只有一个元素包含 activity:object 元素,因此我需要在 content 之前访问它。有没有其他方法可以访问带有我不知道的命名空间的 XML 元素?
    • activity:object 之前的命名空间是什么?
    • 我刚刚修改了主帖中的 XML 以反映对完整字符串的更准确视图。它只是包裹在&lt;entry&gt; 中。这就是为什么我首先尝试通过 xpath 访问&lt;activity:object&gt;
    • @ShawnWhite - 修改代码以直接通过 $post->xpath('//content');
    • @ShawnWhite,您决定使用哪种方法?请发表评论。
    【解决方案3】:

    print_r 总是对 SimpleXMLElement 产生误导。例如,您的输出:

    代码参考:

    $testate = $post->xpath('activity:object')[0]->content;
    print_r($testate);
    

    输出:

    SimpleXMLElement Object
    (
        [0] => 
    This is the value I'm trying to get
    
    )
    

    这并不意味着您需要使用数组索引零 ([0]) 来访问要查找的文本。实际上,虽然这并不意味着,但这并不意味着这是不可能的。令人困惑,我知道。

    但是,您要查找的是字符串值,而不是对象(值)。您需要做的就是转换为字符串:

    $testate = $post->xpath('activity:object')[0]->content;
    $text    = (string) $testate;
               ########
    

    这里的重要部分实际上是转换为字符串。就像 print_r 已经向您建议的那样,使用零索引也可以:

    $text    = (string) $testate[0];
    

    但是零索引不是必需的,只是内部信息。

    重要的是要随身携带:不要依赖 print_rSimpleXMLElement。它是一个对象,print_r 只是在这里告诉你它是一个对象以及它的名称(它是哪种对象类型),它在大括号内输出的其余部分是该对象的内部信息。它绝不是您所拥有的 XML 的全貌。即使最初看起来是这样。

    所以这里只是一个大警告,请记住这一点。考虑转换为字符串(或与字符串函数一起使用,如trim()),就可以了。

    别忘了通读 PHP 手册中的Basic SimpleXML usage

    P.S.:正如另一个答案所示,您不是唯一一个在描述 SimpleXML 的神奇本质时遇到问题的人。

    PPS:您可能想尽快了解 XML-Namespaces,即元素名称包含冒号(您可能已经这样做了,我无法从您的代码中确定)。 p>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-27
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 2013-06-04
      • 1970-01-01
      相关资源
      最近更新 更多