2011-12-14 4 views
0

Я использую комбинацию XMLReader и simpleXML для анализа сообщений в файле экспорта WordPress. Я понимаю, что это немного не соответствует норме, но это больше для резервного проекта, поэтому мы можем легко подтянуть одну из этих статей, если нам это нужно в futre. Сайт WP, на котором они были, должен спуститься.XMLReader & simpleXML Combo, с условиями

Проблема, с которой я сталкиваюсь, заключается в том, что некоторые из узлов в XML-файле пусты или содержат бесполезные значения (т. Е. Не полные сообщения). Мне нужно добавить некоторые условия длины строки, но я не уверен, как проверить их.

<?php 

$path_to_xml_file = 'compress.zlib://wordpress.2011.xml.gz'; 


$reader = new XMLReader(); 
       $reader->open($path_to_xml_file); 
       while($reader->read()) 
       { 
         if($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'item') 
         { 
             $doc = new DOMDocument('1.0', 'UTF-8'); 
             $xml = simplexml_import_dom($doc->importNode($reader->expand(),true)); 
             //echo $xml->title; //or whatever 

// Take care of the articles 
$newcontent = $xml->children('http://purl.org/rss/1.0/modules/content/'); 
$contentString = $newcontent->encoded; 
$titleString = $xml->title; 

    echo ' 
    <div class="article-container" id="article-' . $xml->title . '"> 
    <a href="#top" class="top-link">Back to the Top</a> 
     <h2>' . $xml->title . '</h2> 
     <div class="articles">' . $newcontent->encoded . '</div> 
    </div>'; 
         } 
       } 

?> 

Я был в состоянии успешно проверить это только с SimpleXML, но это было слишком много борова памяти все само по себе. Это был мой SimpleXML код:

<?php 

    $url = 'wordpress.2011.xml.gz'; 
    $xml = new SimpleXMLElement("compress.zlib://$url", NULL, TRUE); 

    foreach ($xml->item as $item) : 

    $newcontent = $item->children('http://purl.org/rss/1.0/modules/content/'); 

    ?> 

<?php 
$contentString = $newcontent->encoded; 
$titleString = $item->title; 

if ((strlen($contentString) < 13) || (strlen($titleString) < 5)) { 
    echo ''; 
} else { 
    echo ' 
    <div class="article-container" id="article-' . $item->title . '"> 
    <a href="#top" class="top-link">Back to the Top</a> 
     <h2>' . $item->title . '</h2> 
     <div class="articles">' . $newcontent->encoded . '</div> 
    </div>'; 
} 
?> 



<?php endforeach; ?> 

UPDATE

С помощью Фрэнсиса, она работает. Вот код:

<?php 

$path_to_xml_file = 'compress.zlib://wordpress.2011.xml.gz'; 

$reader = new XMLReader(); 
$reader->open($path_to_xml_file); 
$contentNS = 'http://purl.org/rss/1.0/modules/content/'; 
while($reader->read()) { 
    if($reader->nodeType == XMLReader::ELEMENT and $reader->name == 'item') { 
     $doc = new DOMDocument('1.0','UTF-8'); 
     $xml = simplexml_import_dom($doc->importNode($reader->expand(), true)); 
     $titleString = (string) $xml->title; 
     $contentString = (string) $xml->children($contentNS)->encoded; 
     if (strlen($contentString) > 12 and strlen($titleString) > 4) { 
      // Be careful with your output escaping! 
      // This below looks like it might be wrong: 
      // - $titleString for an ID (use slug) 
      // - $titleString not escaped 
      // - $contentString should be escaped? not sure here. 
      // Have you considered using XMLWriter()? 
      echo ' 
<div class="article-container" id="article-' . $titleString . '"> 
    <a href="#top" class="top-link">Back to the Top</a> 
    <h2>' . $titleString . '</h2> 
    <div class="articles">' . $contentString . '</div> 
</div>'; 
     } else { 

     echo''; 

     } 

     $reader->next(); //skip the subtrees, go to next item sibling 
     // we already expand()ed this so we don't need to walk it. 
    } 
} 

?> 

ответ

2

Когда вы говорите $contentString = $newcontent->encoded, тип $contentString не string но SimpleXMLElement. Таким образом strlen() возвращает что-то бессмысленное.

Вы должны явно привести SimpleXMLElement с до string, чтобы получить текстовое значение элемента:

$contentString = (string) $newcontent->encoded; 

как в сторону, вы можете упростить расширение DOM и преобразование в SimpleXMLElement, используя дополнительный аргумент в XMLReader::expand():

$sxe = simplexml_import_dom($reader->expand(new DOMDocument('1.0','UTF-8'))); 

EDIT с полным примером вашего первый блок кода, написанный для того, чтобы делать то, что вы хотите (я думаю?). Как вы можете видеть все, что я сделал, это взять внутренний цикл из вашего второго примера кода и поместить его во внутренний цикл в первом примере кода.

$reader = new XMLReader(); 
$reader->open($path_to_xml_file); 
$contentNS = 'http://purl.org/rss/1.0/modules/content/'; 
while($reader->read()) { 
    if($reader->nodeType == XMLReader::ELEMENT and $reader->name == 'item') { 
     $xml = simplexml_import_dom($reader->expand(new DOMDocument('1.0', 'UTF-8'))); 
     $titleString = (string) $xml->title; 
     $contentString = (string) $xml->children($contentNS)->encoded; 
     if (strlen($contentString) > 12 and strlen($titleString) > 4) { 
      // Be careful with your output escaping! 
      // This below looks like it might be wrong: 
      // - $titleString for an ID (use slug) 
      // - $titleString not escaped 
      // - $contentString should be escaped? not sure here. 
      // Have you considered using XMLWriter()? 
      echo ' 
<div class="article-container" id="article-' . $titleString . '"> 
    <a href="#top" class="top-link">Back to the Top</a> 
    <h2>' . $titleString . '</h2> 
    <div class="articles">' . $contentString . '</div> 
</div>'; 
     } 
     $reader->next(); //skip the subtrees, go to next item sibling 
     // we already expand()ed this so we don't need to walk it. 
    } 
} 
+0

Ah okay. Так вот как я проверяю длины. Но, мой реальный вопрос - как я могу проверить каждый, а не весь документ? – Batfan

+0

Что вы подразумеваете под «каждым»? Разве ваш второй блок кода не делает то, что вы хотите? Затем просто переместите свои 'strlen()' проверки во внутренний цикл вашего первого блока кода. –

+0

Он сделал, но, простой XML сам использовал слишком много памяти. Поскольку этот новый комбинированный метод не использует функциональность «foreach», я не уверен, как проверить каждый из указанных узлов для этих 2 условий. – Batfan