Получение текстовой части узла с использованием php Simple XML

Учитывая 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 (очевидно, с целью потребления данных, а не просто возврата его, как в этом простом примере)?

Спасибо, Н.

Могут быть способы добиться того, что вы хотите использовать только SimpleXML, но в этом случае самым простым способом это использовать DOM . Хорошей новостью является то, что если вы уже используете SimpleXML, вам не нужно ничего менять, поскольку DOM и SimpleXML в основном взаимозаменяемы :

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

Предполагая, что ваша задача – перебирать каждую <article/> и получать ее содержимое, ваш код будет выглядеть так:

 $articles = simplexml_load_string($xml); foreach ($articles->article as $article) { $articleText = dom_import_simplexml($article)->textContent; } 
 node->asXML();// It's the simple solution i think !! 

Итак, простой ответ на мой вопрос: 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); 

Вы также можете загрузить xml с помощью simpleXML, а затем преобразовать его в DOM, используя dom_import_simplexml (), как сказал Джош. Это было бы полезно, если вы используете simpleXml для фильтрации узлов для синтаксического анализа, например, с помощью XPath.

Тем не менее, я фактически не использую simpleXML, поэтому для меня это займет много времени.

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

Спасибо вам за помощь!

Вы можете получить текстовый узел элемента DOM с помощью simplexml, просто обработав его как строку:

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

Однако это печатает:

 This is a link with some text following it. TitleTitle 

… потому что текстовый узел рассматривается как один блок, и нет способа определить, где ребенок помещается внутри текстового узла. Кроме того, дочерний узел добавляется дважды из-за другого {}, но вы можете просто извлечь его.

Извините, если я не очень помог, но я не думаю, что есть какой-то способ узнать, где дочерний узел подходит в текстовом узле, если XML не согласован (но тогда почему бы не использовать теги). Если вы знаете, какой элемент вы хотите удалить из текста, strip_tags() будет работать отлично.

На это уже был дан ответ, но CASTING TO STRING (т.е. $ sString = (string) oSimpleXMLNode-> TagName) всегда работал для меня.

Как и @tandu, это невозможно, но если вы можете изменить свой XML, это будет работать:

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

Попробуй это:

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

Это в значительной степени эквивалентно:

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