tags:

views:

1518

answers:

4
<root>
  <thing>
    <specs>
      <spec1 />
      <spec3 />
      <spec2 />
    </specs>
    <details />
    <more_info>
      <info1 />
      <info2 />
    </more_info>
  </thing>
</root>


okeee so i got this sample xml and the problem is i cant seem to get the values of the innerxml,
when i use $reader->readInnerXML() it returns the whole string though im sure that my xml is valid
what i wanted was to get the values of spec1, spec2, spec3 separately

the code is pretty long so i posted it here
i've been stuck with this for 3days now T_T poor me, i'd gladly accept any corrections

A: 

That's working as advertised:

readInnerXML

Reads the contents of the current node, including child nodes and markup.

I think your confusion could be between nodes and attributes. <spec1 /> is not an attribute - it's a node without any children. Writing <spec1 /> is just short hand for <spec1></spec1>. So what you need is either to use actual attributes:

<root>
  <thing>
    <specs spec1="" spec3="" spec2="" />
    <details />
    <more_info info1="" info2="" />
  </thing>
</root>

or read those nodes.

Anyway. I'm not sure if this is just because you're showing us some example code or not, but naming nodes spec1, spec2, spec3 etc. is probably not a good idea. Node names don't need to be unique in XML.

troelskn
A: 

Not sure if this is what you're asking, but simplexml can be used to read xml data (the values of each of the elements, not the attributes). For your thing/specs example, doing this:

$xmlobj = simplexml_load_file($xmlfile);
$extracteddata = $xmlobj->thing->specs->spec1;

would give you the contents of the spec1 element.

Ex: If the element was <spec1>1234</spec1> the above code would return "1234"

benmmc
uhm i've read in the docs (user comments) that simple xml is not good for xml files that are pretty large... so i resorted to xmlreaderas the file im working on is about 46mb
lock
+1  A: 

It depends what you mean by "value". If you have something like

<spec3 />Value</spec3>

Then readInnerXML should be giving you your value.

If your value is in an attribute,

<spec1 foo="my attribute" />

You'll need to use the getAttribute method of the XMLReader object, or explicitly tell the reader to start parsing attributes. See the code example below for a few ways to accomplish this.

Finally, if the node contains more nested XML,

<spec2><foo><baz thing="la de da">Value</baz></foo></spec2>

There's no direct way at that moment in time for the reader to understand values/elements inside of it. You'd need to do one of the following

  1. Change you reader parsing code to hook into elements at those depths
  2. Take the XML chunk from readInnerXML and start parsing it with a second XMLReader instance,
  3. Take the XML chunk from readInnerXML and start parsing it with a another XML parsing library.

Here's some example code for parsing attributes

$reader = new XMLReader();
$reader->xml(trim('
<root>
  <thing>
 <specs>
   <spec1 foo="my attribute">Value</spec1>
   <spec3>
   My Text
   </spec3>
   <spec2 foo="foo again" bar="another attribute" baz="yet another attribute" />
 </specs>
 <details />
 <more_info>
   <info1 />
   <info2 />
 </more_info>
  </thing>
</root> 
'));

$last_node_at_depth = array();
$already_processed  = array();
while($reader->read()){
 $last_node_at_depth[$reader->depth] = $reader->localName;
 if(
 $reader->depth > 0 && 
 $reader->localName != '#text' &&   
 $last_node_at_depth[($reader->depth-1)] == 'specs' &&
 !in_array ($reader->localName,$already_processed)
 ){   
  echo "\n".'Processing ' . $reader->localName . "\n";
  $already_processed[] = $reader->localName;
  echo '--------------------------------------------------'."\n";
  echo 'The Value for the inner node ';         
  echo ' is [';
  echo trim($reader->readInnerXML());
  echo ']'."\n";

  if($reader->attributeCount > 0){
   echo 'This node has attributes, lets process them' . "\n";

   //grab attribute by name
   echo '    Value of attribute foo: ' . $reader->getAttribute('foo') . "\n";

   //or use the reader to itterate through all the attributes
   $length = $reader->attributeCount;
   for($i=0;$i<$length;$i++){
    //now the reader is pointing at attributes instead of nodes
    $reader->moveToAttributeNo($i);
    echo '    Value of attribute ' . $reader->localName;
    echo ': ';
    echo $reader->value;
    echo "\n";
   }
  }
  //echo $reader->localName . "\n";        
 }        
}
Alan Storm
A: 

I am having trouble ever seeing the XMLREADER::ATTRIBUTE node type hold true, regardless of whether the XML has attributes in a node or not. Incidentally, the code recognises the attribute when using a $xml_feed_read->hasAttributes statement. I have even placed a debug print in a switch/case selection under the XMLREADER::ATTRIBUTE to fire when it detects, and nothing happens.

Has anyone successfully identified an ATTR using this node type?

Edit: I have even added a "print node type value" debug statement on each iteration of the while ... read() loop on the XMLReader class and it never, despite attributes existing, displays a XMLReader::ATTRIBUTE = 2 value at all. Very strange, unless I am missing something here.

alexcn