作者:傲气战歌网 来源:www.27zg.com 发表时间:2014-03-24 03:02
You can also run XPath queries. They are run using the SimpleXMLElement::xpath() method that method takes a single argument, the XPath query. If we wanted to select all the book titles we could do something like this:
<?php $titles = $books->xpath('book/title'); foreach($titles as $title) { echo $title.PHP_EOL; } ?>All ISBN numbers would be retrieved like this:
<?php $isbn = $books->xpath('book/@isbn'); foreach($isbn as $isbn) { echo $isbn.PHP_EOL; } ?>You can of course use any valid XPath query. The method will always return an array.
Parsing RSS feedsNow let's try to parse some real-world data. We'll use the RSS feed from the forums.
<?php $rss = new SimpleXMLElement('http://www.phpfreaks.com/forums/index.php?type=rss;action=.xml', null, true); echo "<h1><a href='{$rss->channel->link}'>{$rss->channel->title}</a></h1>".PHP_EOL.'<hr />'.PHP_EOL; foreach($rss->xpath('channel/item') as $item) { echo <<<EOF <h2><a href='{$item->link}'>{$item->title}</a></h2> <div>Posted at: {$item->pubDate}</div> {$item->description} <hr /> EOF; } ?>This was in fact the RSS reader I promised you on page 1. If you expected something fancy I suppose I've disappointed you. If you want to make it fancy then just get started, add some AJAX, a spiffy interface and soon you'll be competing with
Google Reader.
As you see, parsing XML data is simple with SimpleXML when you already know the structure of the XML data, but what if you want to parse something which you don't already know the structure of? We'll take a look at that now, but we'll still use our books.xml file.
<?php function parse_recursive(SimpleXMLElement $element, $level = 0) { $indent = str_repeat("\t", $level); // determine how much we'll indent $value = trim((string) $element); // get the value and trim any whitespace from the start and end $attributes = $element->attributes(); // get all attributes $children = $element->children(); // get all children echo "{$indent}Parsing '{$element->getName()}'...".PHP_EOL; if(count($children) == 0 && !empty($value)) // only show value if there is any and if there aren't any children { echo "{$indent}Value: {$element}".PHP_EOL; } // only show attributes if there are any if(count($attributes) > 0) { echo $indent.'Has '.count($attributes).' attribute(s):'.PHP_EOL; foreach($attributes as $attribute) { echo "{$indent}- {$attribute->getName()}: {$attribute}".PHP_EOL; } } // only show children if there are any if(count($children)) { echo $indent.'Has '.count($children).' child(ren):'.PHP_EOL; foreach($children as $child) { parse_recursive($child, $level+1); // recursion :) } } echo $indent.PHP_EOL; // just to make it "cleaner" } $xml = new SimpleXMLElement('books.xml', null, true); parse_recursive($xml); ?>Note: If you wish run that through your browser make sure to add header('Content-type: text/plain'); before anything is output so the browser will know it's plain text and not HTML we are serving.
We've used recursion which means that we theoretically will be able to parse any XML document no matter how many times nested data there is (this is of course not possible due to script execution time etc.).
In the script I decided that if there are any children then we won't display any possible value. This is because of the way I've decided to output it. Had you chosen to use HTML to output it or chosen to put it in an array then you could have taken the value as well.
That's it for parsing XML documents. Next we'll change documents.
Altering XML data with PHP DOMAnother thing I would like to introduce you to is PHP DOM. It's much more powerful than SimpleXML and we'll be using this for the remainder of the tutorial.
Adding nodesStill using books.xml we now want to add a new how many pages there are in each book and save it as books2.xml.
<?php // isbn => pages $page_numbers = array( '978-1594489501' => '384', // A Thousand Splendid Suns '978-1594489587' => '352', // The Brief Wondrous Life of Oscar Wao '978-0545010221' => '784', // Harry Potter and the Deathly Hallows ); $dom = new DOMDocument(); $dom->load('books.xml'); $xpath = new DOMXPath($dom); $books = $xpath->query('book'); foreach($books as $book) { $book->appendChild($dom->createElement('pages', $page_numbers[$book->getAttribute('isbn')])); } $dom->save('books2.xml'); ?>First we have an array of ISBN numbers and page numbers. Then we create a new instance of DOMDocument and load our file into it. Next we'll create an instance of DOMXPath and pass our $dom object to it. Then we run an XPath query saying "select all nodes elements called 'book'". This will return an instance of DOMNodelist. If you want to access a specific item then you can use DOMNodelist::item(). That method takes one argument, the index of the element you wish to retrieve. The indices are named similarly to the indices of an array (starting from 0).
Inside the loop we do the following:
Finally we save the file as books2.xml. We could have chosen to output it instead, and then the last line should have been replaced with:
echo $dom->saveXML();When selecting all the book elements we could also have used DOMDocument::getElementsByTagName():
$books = $dom->getElementsByTagName('book');Changing data下一篇:常用RSS阅读器评测