【问题标题】:Getting the text portion of a node using php Simple XML使用 php Simple XML 获取节点的文本部分
【发布时间】:2011-07-05 04:06:26
【问题描述】:

给定php代码:

$xml = <<<EOF
<articles>
<article>
This is a link
<link>Title</link>
with some text following it.
</article>
</articles>
EOF;

function traverse($xml) {
    $result = "";
    foreach($xml->children() as $x) {
        if ($x->count()) {
            $result .= traverse($x);
        }
        else {
            $result .= $x;
        }
    }
    return $result;
}

$parser = new SimpleXMLElement($xml);
traverse($parser);

我希望函数 traverse() 返回:

This is a link Title with some text following it.

但是,它只返回:

Title

有没有办法使用 simpleXML 获得预期的结果(显然是为了消费数据,而不是像这个简单的例子那样仅仅返回它)?

【问题讨论】:

    标签: php simplexml


    【解决方案1】:

    试试这个:

    $parser = new SimpleXMLElement($xml);
    echo html_entity_decode(strip_tags($parser->asXML()));
    

    这几乎等同于:

    $parser = simplexml_load_string($xml);
    echo dom_import_simplexml($parser)->textContent;
    

    【讨论】:

      【解决方案2】:

      这已经得到了回答,但是 CASTING TO STRING(即 $sString = (string) oSimpleXMLNode->TagName)总是对我有用。

      【讨论】:

      • echo (string)$xmlNode;
      【解决方案3】:
      node->asXML();// It's the simple solution i think !!
      

      【讨论】:

      • 你用 OP 的数据试过这个吗?它真的有效吗?
      【解决方案4】:

      所以,我的问题的简单答案是:Simplexml 无法处理这种 XML。请改用 DomDocument。

      这个例子展示了如何遍历整个 XML。似乎 DomDocument 可以处理任何 XML,而 SimpleXML 要求 XML 简单。

      function attrs($list) {
          $result = "";
          foreach ($list as $attr) {
              $result .= " $attr->name='$attr->value'";
          }
          return $result;
      }
      
      function parseTree($xml) {
          $result = "";
          foreach ($xml->childNodes AS $item) {
              if ($item->nodeType == 1) {
                  $result .= "<$item->nodeName" . attrs($item->attributes) . ">" . parseTree($item) . "</$item->nodeName>";
              }
              else {
                  $result .= $item->nodeValue;
              }
          }
          return $result;
      }
      
      $xmlDoc = new DOMDocument();
      $xmlDoc->loadXML($xml);
      
      print parseTree($xmlDoc->documentElement);
      

      您还可以使用 simpleXML 加载 xml,然后使用 dom_import_simplexml() 将其转换为 DOM,正如 Josh 所说。如果您使用 simpleXml 过滤节点以进行解析,这将很有用,例如使用 XPath。

      但是,我实际上并没有使用 simpleXML,所以对我来说这需要很长的路要走。

      $simpleXml = new SimpleXMLElement($xml);
      $xmlDom = dom_import_simplexml($simpleXml);
      
      print parseTree($xmlDom);
      

      感谢大家的帮助!

      【讨论】:

        【解决方案5】:

        可能有一些方法可以仅使用 SimpleXML 来实现您想要的,但在这种情况下,最简单的方法是使用 DOM。好消息是,如果您已经在使用 SimpleXML,则无需更改任何内容,因为 DOM 和 SimpleXML 是 basically interchangeable

        // either
        $articles = simplexml_load_string($xml);
        echo dom_import_simplexml($articles)->textContent;
        
        // or
        $dom = new DOMDocument;
        $dom->loadXML($xml);
        echo $dom->documentElement->textContent;
        

        假设您的任务是遍历每个 &lt;article/&gt; 并获取其内容,您的代码将如下所示

        $articles = simplexml_load_string($xml);
        foreach ($articles->article as $article)
        {
            $articleText = dom_import_simplexml($article)->textContent;
        }
        

        【讨论】:

        • 这实际上产生了我所期望的确切结果 - 没有真正解决遍历 Xml 文档的潜在问题。
        • 您将无法使用 SimpleXML“遍历”或迭代文本节点。或者至少,如果可能的话,这将是人为的/不切实际的。使用 SimpleXML 使事情变得更容易,然后将选定的节点导入 DOM 以访问不属于 SimpleXML 的功能。
        【解决方案6】:

        就像@tandu 说的那样,这是不可能的,但如果你可以修改你的 XML,这将起作用:

        $xml = <<<EOF
        <articles>
            <article>
                This is a link
            </article>
            <link>Title</link>
            <article>
               with some text following it.
            </article>
        </articles>
        

        【讨论】:

          【解决方案7】:

          你可以用simplexml获取一个DOM元素的文本节点,只要把它当作一个字符串来处理:

          foreach($xml->children() as $x) {
             $result .= "$x"
          

          但是,这会打印出来:

          This is a link
          
          with some text following it.
          TitleTitle
          

          ..因为文本节点被视为一个块,并且无法判断子节点在文本节点内的位置。由于另一个 else {},子节点也被添加了两次,但您可以将其取出。

          对不起,如果我没有提供太多帮助,但我认为没有任何方法可以找出子节点在文本节点中的位置,除非 xml 是一致的(但是,为什么不使用标签)。如果您知道要从哪个元素中去除文本,strip_tags() 会很好用。

          【讨论】:

          • 知道你想要完成的事情是不可能的,这总是有帮助的。不幸的是,我不拥有 XML,所以它就是这样。你知道 php 中的其他解析器是否更适合我的任务?
          • 我不知道任何现有的......也许你可以写一个!
          • 在找错(解析器?)树很长一段时间后,似乎 DOM 是我们处理此类 XML 时需要的朋友。
          • 如果您准备编写更多代码,我发现 XMLReader 拉式解析器能够处理标签汤。但是,没有可用的 xpath,因此您必须在解析汤时自己携带上下文信息。
          猜你喜欢
          • 2017-09-10
          • 1970-01-01
          • 2013-04-01
          • 2012-12-03
          • 2011-09-03
          • 2010-10-20
          • 1970-01-01
          • 2011-12-19
          • 2012-04-08
          相关资源
          最近更新 更多