tags:

views:

94

answers:

4

I asked a similar question last week but did not get an answer that really nailed it. I suspect the question needs to be stated more plainly so here goes:

Given this XML:

<?xml version="1.0" encoding="utf-8"?>
<everyone>
  <guest>
    <name>Joseph Needham</name>
    <age>53</age>
  </guest>
  <guest>
    <name>Lu Gwei-djen</name>
    <age>31</age>
  </guest>
</everyone>

How do I return precisely this:

  <guest>
    <name>Joseph Needham</name>
    <age>53</age>
  </guest>
  <guest>
    <name>Lu Gwei-djen</name>
    <age>31</age>
  </guest>

I don't want a simplexml object, I don't want to convert anything, I don't want just the values of nodes, I don't want a new XML document with its corresponding header... just that chunk of XML. Can't use external libraries... nothing that doesn't come with a standard, average PHP install. How do I extract one out of the other?

My best guess? Use DomDocument to get the nodes names and content somehow and then rebuild what I want by using a foreach loop and echoing out the various node names and values including line endings to format everything properly. However, this seems like it could be amazingly clunky. I suspect there is a simpler way to do it so I want to see if anyone here on stackoverflow know what that way is (or can tell me that there is, in fact, NOT an easier way). Thanks in advance.

+1  A: 
preg_match('`<guest>.*</guest>`is', $xml, $matches);
print_r($matches);
Kamil Szot
+2  A: 
$reader = new XMLReader();
$reader->xml($xml_str);
$reader->read();
$inner = $reader->readInnerXML();

// $inner is your desired xml string.

One advantage of using XMLReader is that it uses less memory than SimpleXML or the DOM classes. Another is that it's very fast.

GZipp
I thought this would be fastest as well but when I bench marked it against the other solutions it turned out to be the slowest. Using an XML file with a thousand nodes to be selected the other solutions were generally about 60% as long to complete (that simplexmlelement xpath solution averaged 5.8 ms while this XMLReader based solution averaged 10 ms) Maybe I did something wrong. Thanks for the advice, though. Helped me understand the whole thing better.
rg88
I just tested this myself on a very large file and you're right; it is slower than SimpleXML and DOMXPath, and by about the same ratio as your tests showed. That surprises me, also, since I've found it to be generally faster when retrieving all the data, node by node, from large files.
GZipp
+2  A: 
$string = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<everyone>
  <guest>
    <name>Joseph Needham</name>
    <age>53</age>
  </guest>
  <guest>
    <name>Lu Gwei-djen</name>
    <age>31</age>
  </guest>
</everyone>

XML;

$xml = new SimpleXMLElement($string);
$nodes = $xml->xpath('/everyone/guest');

$result = '';
foreach ( $nodes as $node ) {
  $result .= $node->asXML()."\n";
}
echo $result;
die;
Derek Illchuk
This was easy to do and was as fast or faster than the other solutions. I appreciate the help.
rg88
+2  A: 

Something like this (using XPath - if you have another way to get a list of the guest elements, you can use that) should do the trick.

$xml = '';
$xpath = new DOMXPath($document);
foreach($xpath->query('//everyone/guest') as $guestNode) {
    $xml .= $document->saveXML($guestNode);
}
BlackAura
This worked but for some reason I kept getting extra space added to things. I could remove it with trim(), I suppose. Thanks for the advice.
rg88