我想使用XMLReader读取XML文件,但在解析期间,每个元素都会调用两次END ELEMENT.
<publications>
<article id="Xu86oazdn">
<title>Learning</title>
<authors>
<author>
<firstname>Michel</firstname>
<lastname>Browsky</lastname>
</author>
</authors>
</article>
</publications>
Run Code Online (Sandbox Code Playgroud)
这是解析作者条目的一段代码:
<?php
$xml = new XMLReader();
$xml->open("php://stdin");
$author = null;
while($xml->read()) {
switch($xml->nodeType) {
case XMLReader::ELEMENT:
switch($xml->name) {
case 'author':
echo("+" . $xml->name);
break;
}
case XMLReader::END_ELEMENT:
switch($xml->name) {
case 'author':
echo("-" . $xml->name);
break;
}
}
}
?>
Run Code Online (Sandbox Code Playgroud)
但奇怪的是,每个调用END_ELEMENT两次</author>,如echo消息所示:
+author
-author
-author
Run Code Online (Sandbox Code Playgroud)
如果我通过调用替换echo消息$xml->readOuterXML(),则第一个END_ELEMENT如下:
<author>
<firstname>Michel</firstname>
<lastname>Browsky</lastname>
</author>
Run Code Online (Sandbox Code Playgroud)
第二个是以下内容:
<author/>
Run Code Online (Sandbox Code Playgroud)
我的代码出了什么问题?我是否以错误的方式使用END_ELEMENT?检测末端元素的正确方法是什么?
break在第一个switch条件结束后添加一个语句nodeType:
<?php
$xml = new XMLReader();
$xml->open("php://stdin");
while($xml->read()) {
switch($xml->nodeType) {
case XMLReader::ELEMENT:
switch($xml->name) {
case 'author':
echo("+" . $xml->name);
break;
}
// THIS LINE IS MISSING
break;
case XMLReader::END_ELEMENT:
switch($xml->name) {
case 'author':
echo("-" . $xml->name);
break;
}
}
}
?>
Run Code Online (Sandbox Code Playgroud)
break阅读之后添加另一个END_ELEMENT,如果仅用于对称性.
case XMLReader::END_ELEMENT:
switch($xml->name) {
case 'author':
echo("-" . $xml->name);
break;
}
}
break;
Run Code Online (Sandbox Code Playgroud)
问题发生在编码风格上.简化代码.例如:
$xml = new XMLReader();
$xml->open("php://stdin");
while($xml->read()) {
switch($xml->nodeType) {
case XMLReader::ELEMENT: {
startElement( $xml->name );
break;
}
case XMLReader::END_ELEMENT: {
endElement( $xml->name );
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以进一步简化.PHP有一个XML编组软件包,但您也可以将代码抽象为类.然后,这些类的实例将能够从XML文件中读取(或写入)自身.例如:
$xml = new XMLReader();
$xml->open("php://stdin");
while($xml->read()) {
if( $xml->name == 'author' ) {
$author = new Author();
$author->marshall( $xml );
}
}
Run Code Online (Sandbox Code Playgroud)
这将对象存储的细节与对象本身相关联.每次更改Author对象时,您都知道必须更改它自动编组的方式.您可以使用适当的设计模式,XML模式等进一步抽象和扩展这些概念.
因此,您的最终代码可能类似于:
$xml = new XMLReader();
$xml->open( "php://stdin" );
$publications = new Publications();
$publications->marshall( $xml );
Run Code Online (Sandbox Code Playgroud)
该Publications对象负责读取XML文档,并在出现关联的XML标记时实例化相应的类:
while($xml->read()) {
$article = new Article();
$article->marshall( $xml );
add( $article );
}
Run Code Online (Sandbox Code Playgroud)
使用PHP编组框架可以节省您的时间和精力.考虑XML_Serializer:
| 归档时间: |
|
| 查看次数: |
3635 次 |
| 最近记录: |