Hello,

I need to convert the followwing code from C# to PHP:

XmlDocument doc = new XmlDocument();
doc.Load("C:\\test.xml");

XmlNode root = doc.FirstChild;
for (int i = 0; i < root.ChildNodes.Count; i++) {
       string innerText += root.ChildNodes[i].InnerXml;
}

The idea is to loop through child nodes in xml file and get the inner xml content.

Many Thanks
Rocco

    So I'm guessing that the difference between node.InnerXML and $doc->saveXML($node) is that the latter has $node's enclosing tags around the result?

      Well, the idea is to displays all the child nodes of the root element. So they may contain sub nodes which I want also to include. But I care only for the first child of the root. In my example I'm trying to parse ul/li list and get each child in array. Below is the code I'm trying to parse:

      <ul>
            <li><a href="#">Item 1</a> </li>
            <li>Item 2<ul>
              <li>Item 2.1 <ul>
                <li><a href="#">Item 2.1.1</a> </li>
                <li><a href="#">Item 2.1.2</a> </li>
              </ul></li>
              <li><a href="#">Item 2.2</a> </li>
              <li><a href="#">Item 2.2.1</a> </li>
            </ul></li>
            <li>Item 3 <ul>
              <li><a href="#">Item 3.1</a> </li>
              <li><a href="#">Item 3.1</a> </li>
            </ul></li>
      </ul>

      So is $doc->saveXML($node) the php equivalent for node.InnerXML?

      Thanks in advance for your help!
      Rocco

        rocco2004 wrote:

        So is $doc->saveXML($node) the php equivalent for node.InnerXML?

        Isn't that what I just asked? I'm going to make a wild guess and say that my guess is right. So the equivalent would loop over all the child nodes of the given element and concatenate their saveXML() values together.

        rocco2004 wrote:

        But I care only for the first child of the root.

        Then it sounds like .InnerXML (or any of its equivalents) probably isn't even what you want in the first place. It sounds like what you want is $ulnode->getElementsByTagName('li')->item(0).

          Hello again,

          Sorry to bother again but I feel like I can't get the right syntax for doing it. Below is my code:

          $xmlDoc = new SimpleXMLElement('<ul> <li><a href="#">Item 1</a> </li> <li>Item 2<ul> <li>Item 2.1 <ul> <li><a href="#">Item 2.1.1</a> </li> <li><a href="#">Item 2.1.2</a> </li> </ul></li> <li><a href="#">Item 2.2</a> </li>       <li><a href="#">Item 2.2.1</a> </li> </ul></li> <li>Item 3 <ul> <li><a href="#">Item 3.1</a> </li> <li><a href="#">Item 3.1</a> </li> </ul></li> </ul>');
          
          for ($i = 0; $i < count($xmlDoc->children()); $i++){
          		$innerXML = $xmlDoc->saveXML($xmlDoc[$i]);
          }
          

          $innerXML simply returns false.
          I've read that I have to use documentElement when using saveXML but not sure how to implement it?

          Many thanks
          Rocco

            Personally I use the [man]DOM[/man] interface, as it's more standardised and probably more familiar from other languages (like C#). After doing a bit of research, it would appear that Microsoft's InnerXML property is equivalent to

            function InnerXML($doc,$node)
            {
            	$innerXML = '';
            	foreach($node->childNodes as $child)
            		$innerXML .= $doc->saveXML($child);
            	return $innerXML;
            }
            

            where $doc is the XML document, and $node is the node for which the InnerXML is wanted.

              I still can't find out how exactly DOM interface is parsing the xml. Here is my code:

              $doc = DOMDocument::loadXML('<ul>
                  <li><a href="#">Item 1</a> </li>
                  <li>Item 2<ul>
                    <li>Item 2.1 <ul>
                      <li><a href="#">Item 2.1.1</a> </li>
                      <li><a href="#">Item 2.1.2</a> </li>
                    </ul></li>
                    <li><a href="#">Item 2.2</a> </li>
                    <li><a href="#">Item 2.2.1</a> </li>
                    <li><a href="#">Item 2.2.2</a> </li>
                  </ul></li>
                  <li>Item 3 <ul>
                    <li><a href="#">Item 3.1</a> </li>
                  </ul></li>
                  <li><a href="#">Item 5</a> <ul>
                    <li><a href="#">Item 5.1</a> </li>
                    <li><a href="#">Item 5.2</a> </li>
                  </ul></li>
                </ul>');
              
              $innerXML2 = '';
              
              foreach ($doc->childNodes as $node) {
              $innerXML2 .= $this->InnerXML($doc,$node);
              }
              /////////////////
              function InnerXML($doc,$node) {
              		$innerXML = '';
              		foreach($node->childNodes as $child)
              			$innerXML .= $doc->saveXML($child);
              		return $innerXML;
              	} 
              

              It's looping only once, so the $innerXML will always return the entire content of the $doc. I want to return the childs like:

              1. <li><a href="#">Item 1</a> </li>
              2. <li>Item 2<ul> <li>Item 2.1 <ul> <li><a href="#">Item 2.1.1</a> </li> <li><a href="#">Item 2.1.2</a> </li></ul></li><li><a href="#">Item 2.2</a> </li><li><a href="#">Item 2.2.1</a> </li><li><a href="#">Item 2.2.2</a> </li></ul></li>
              3. <li>Item 3 <ul> <li><a href="#">Item 3.1</a> </li> </ul></li>
              4. <li><a href="#">Item 4</a> <ul> <li><a href="#">Item 4.1</a> </li> <li><a href="#">Item 4.2</a> </li></ul></li>
              

              I don't mind using any xml object, just to return the list above.

              Many Thanks!
              Rocco

                Well, if you want a list of children, why are you asking about InnerXML and string concatenation? The list of a node's children is already available in $node->childNodes, and you can just look at that.

                $list_elements = array();
                $ul = $doc->childNodes->item(0); // The document has one child - the outermost <ul> element.
                foreach($ul->childNodes as $node)
                {
                    if($node->nodeType==XML_ELEMENT_NODE)
                        $list_elements[] = $doc->saveXML($node);
                }
                

                If you want $list_elements to be a DOMNodeList instead of an array of text strings, you can get fancy:

                $xpath = new DOMXPath($doc);
                $list_children = $xpath->query('li');
                

                  Hello,
                  Your suggestion definitely fixed my problem. Many thanks for that. I just want to understand how saveXML works. So let's say I want to get the inner li nodes for each parent child in the same way... I tried with the code below:

                  $list_elements = array();
                  $list_subElements = array();
                  $ul = $doc->childNodes->item(0); // The document has one child - the outermost <ul> element.
                  foreach($ul->childNodes as $node) {
                      if($node->nodeType==XML_ELEMENT_NODE) {
                          $list_elements[] = $doc->saveXML($node);
                  
                      foreach($node->childNodes as $node2) {
                       $list_subElements[] = $doc->saveXML($node2);
                       }
                  }
                  }
                  

                  In this case $doc->saveXML($node2); will return the internal XML only if it starts with <ul>. If starting with <li> it will get only the text. Not a big deal, but just curious why this is happening.
                  Rocco

                    Um, all of the list items start with <li>, by definition. It just so happens that some of those list items contain <ul> elements (and some for that matter contain <a> elements).

                      Write a Reply...