6

I have a merged xml with a root element and multiple item child elements. Something like this

 <root>
  <item>test1</item>
  <item>test2</item>
 </root>

What I want is an easy way to parse the xml and create an array of xml strings from the items.

$arrXml[0] = '<item>test1</item>';
$arrXml[1] = '<item>test2</item>';

I'm looking for an elegant solution not any solution.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
johnlemon
  • 20,761
  • 42
  • 119
  • 178
  • I don't understand how this is relevant ? I have a particular task with this particular solution. I don't thing the big picture can be changed. I believe I was clear enough in the requirements. – johnlemon Oct 26 '10 at 09:07
  • @user this simply sounds like a really dumb idea. – Pekka Oct 26 '10 at 09:18
  • I can't believe you down vote me for not sharing a bigger picture even if you have experience in development. What I ask for is clear and I don't need a moral lesson. Also if you really need to know a 3th party is sending a big xml file. I need to parse the file and send each client the piece it needs also as an xml. – johnlemon Oct 26 '10 at 09:19
  • 2
    will the elements start and end on the same line? Also, from your bigger picture I'd say this approach is better solved with XSLT or at least without converting to an array. I mean, if you need to send XML back, why tranform to an array? Just pick the parts you need and send them. Btw, good Pekka asked. – Gordon Oct 26 '10 at 09:21
  • @user The reason why I'm asking for the bigger picture is that using string parsing for this is complicated to implement, and likely to invite a shitload of trouble, e.g. with nested structures. Have you considered using native XML functions for the whole process instead? – Pekka Oct 26 '10 at 09:24
  • 1
    possible duplicate of [PHP what is the best approach to using XML? Need to create and parse XML responses](http://stackoverflow.com/questions/2060346/php-what-is-the-best-approach-to-using-xml-need-to-create-and-parse-xml-response) – Gordon Oct 26 '10 at 09:25
  • I edited the question to be able to remove my downvote. I still think it's unwise to do with arrays. – Pekka Oct 26 '10 at 10:39
  • I need to split XML too. Trasforming XMLs is a common task in system integration platforms, like ESB. danip has asked a good question. – xmedeko Aug 03 '11 at 06:33

3 Answers3

7

Ok, like already mentioned in the comments to your question I am not convinced this is really what you should be doing, but since I cant stand SimpleXml and dont want people to think it's the only way, here is how to do it

with DOM:

$arrXml = array();
$dom    = new DOMDocument;
$dom->loadXML( $xml );
foreach( $dom->getElementsByTagName( 'item' ) as $item ) {
    $arrXml[] = $dom->saveXML( $item );
}
print_r( $arrXml );

with XMLReader:

$arrXml = array();
$reader = new XmlReader;
$reader->xml( $xml );
while( $reader->read() ) {
    if( $reader->localName === 'item' && $reader->nodeType === 1 ) {
        $arrXml[] = $reader->readOuterXml();
    }
}
print_r( $arrXml );

and XMLParser*:

xml_parse_into_struct(xml_parser_create(), $xml, $nodes);
$xmlArr = array();
foreach($nodes as $node) {
    if($node['tag'] === 'ITEM') {
        $arrXml[] = "<item>{$node['value']}</item>";
    }
}
print_r($arrXml);

* this can also be done via callbacks triggered when an ITEM element is encountered. Would take more code, but is pretty flexible.

Note that all of the above might need some tweaking depending on your real XML.


Given that the XML in your question (which is likely only an example) is dirt simple and well defined, you can also use explode():

$arrXml = array_map( 'trim',
    array_filter(
        explode( PHP_EOL, $xml ),
        function( $line ) { return substr( $line, 0, 6 ) === '<item>'; }
));
print_r( $arrXml );

or a Regex (read disclaimer below)

preg_match_all('#<item>.*</item>#', $xml, $arrXml);
print_r($arrXml[0]);

Disclaimer Now, just to make sure you are not starting to parse XML with Regex or Explode on a regular basis: The last two approaches are only feasible if your markup is really that clearly defined as you show it.

Gordon
  • 312,688
  • 75
  • 539
  • 559
  • You have not mentioned SimpleXmlElement, it can to xpath lookups. But according to my experience it's asXml() method does not handle namespaces well. – xmedeko Aug 03 '11 at 10:06
2

There are some nice code examples in the comments of SimpleXml manual page. I am sure you can make something work from objectsIntoArray() sample.

renick
  • 3,873
  • 2
  • 31
  • 40
1

Have you looked at SimpleXML?

For example:

$string = "
 <root>
  <item>test1</item>
  <item>test2</item>
 </root>
";

$xml = simplexml_load_string($string);
robjmills
  • 18,438
  • 15
  • 77
  • 121
  • This won't give him what he's asking for. That said, I'm not sure whether what he's asking for is a good idea – Pekka Oct 26 '10 at 09:01
  • @Pekka - yep i know but he wants an elegant solution for parsing XML and simpleXML is just that (imo). Too much margin for error otherwise – robjmills Oct 26 '10 at 09:04
  • 1
    This are the first steps , I agree..but the rest? – johnlemon Oct 26 '10 at 09:05