帮助在php中使用xmlreader读取嵌套的xml

时间:2009-02-09 06:15:23

标签: php xmlreader

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


okeee所以我得到了这个样本xml,问题是我似乎无法得到innerxml的值,当我使用$reader->readInnerXML()时它返回整个字符串虽然我确定我的xml是有效的
我想要的是分别获取spec1,spec2,spec3的值

代码很长,所以我发布了它here 我已经坚持了3天,现在T_T让我很沮丧,我很乐意接受任何更正

3 个答案:

答案 0 :(得分:4)

这取决于你所说的“价值”。如果您有类似

的内容
<spec3 />Value</spec3>

然后readInnerXML应该给你你的价值。

如果您的值在属性中,

<spec1 foo="my attribute" />

您需要使用XMLReader对象的getAttribute方法,或明确告诉读者开始解析属性。有关实现此目的的几种方法,请参阅下面的代码示例。

最后,如果节点包含更多嵌套XML,

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

在那个时刻,读者无法理解其中的价值/元素。您需要执行以下操作之一

  1. 将读者解析代码更改为挂钩到这些深度的元素
  2. 从readInnerXML获取XML块并开始使用第二个XMLReader实例解析它,
  3. 从readInnerXML获取XML块并开始使用另一个XML解析库解析它。
  4. 以下是解析属性的一些示例代码

    $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";        
        }        
    }
    

答案 1 :(得分:0)

那是有效的as advertised

  

<强> readInnerXML

     

读取当前节点的内容,包括子节点和标记。

我认为您的混淆可能在节点和属性之间。 <spec1 />不是属性 - 它是没有任何子节点的节点。写<spec1 />只是<spec1></spec1>的简写。所以你需要的是使用实际属性:

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

或阅读那些节点。

反正。我不确定这是否只是因为您向我们展示了一些示例代码,但命名节点spec1spec2spec3等可能不是一个好主意。节点名称在XML中不需要是唯一的。

答案 2 :(得分:0)

不确定这是否是您所要求的,但simplexml可用于读取xml数据(每个元素的值,而不是属性)。对于你的东西/规格示例,这样做:

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

会给你spec1元素的内容。

例如:如果元素为<spec1>1234</spec1>,则上述代码将返回“1234”