java dom读写xml
用PHP读写可扩展标记语言(XML)似乎有些令人恐惧。 实际上,XML及其所有相关技术可能令人生畏。 但是,用PHP读写XML并不是一项艰巨的任务。 首先,您需要了解一些有关XML的知识-XML的含义和用途。 然后,您需要学习如何在PHP中读取和编写XML,您可以通过多种方式进行操作。
本文提供了有关XML的简短入门,然后说明了如何在PHP中读写XML。
什么是XML?
XML是一种数据存储格式。 它没有定义要存储什么数据或该数据的结构。 XML仅定义标签和这些标签的属性。 格式正确的XML标签如下所示:
<name>Jack Herrington</name>
此<name>
标记包含一些文本:Jack Herrington。
不包含文本的XML标签如下所示:
<powerUp />
用XML编写代码的方法可能不止一种。 例如,此标记产生与上一个相同的输出:
<powerUp></powerUp>
您还可以将属性添加到XML标记。 例如,此<name>
标记包含first
和last
属性:
<name first="Jack" last="Herrington" />
您也可以用XML编码特殊字符。 例如,“&”号的编码如下:
&
包含标签和格式化等提供良好形成的实例中,这意味着标记属性的XML文件是平衡的,且字符被正确编码。 清单1是格式良好的XML的示例。
清单1.一个XML书单示例
<books>
<book>
<author>Jack Herrington</author>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>Podcasting Hacks</title>
<publisher>O'Reilly</publisher>
</book>
</books>
清单1中的XML包含书籍列表。 父<books>
标记包括一组<book>
标记,每个标记都包含<author>
, <title>
和<publisher>
标记。
当标记的结构及其内容由外部架构文件验证时,XML文档才有效。 可以以多种格式指定模式文件。 出于本文的目的,您需要的只是格式良好的XML。
如果您认为XML很像超文本标记语言(HTML),那是对的。 XML和HTML都是基于标记的语言,它们具有许多相似之处。 但是,必须注意,尽管XML文档可以是格式正确HTML,但并非所有HTML文档都是格式良好的XML。 break标签( br
)是XML和HTML之间差异的一个很好的例子。 此换行符是格式正确HTML,但格式不正确的XML:
<p>This is a paragraph<br>
With a line break</p>
此换行符是格式正确的XML和HTML:
<p>This is a paragraph<br />
With a line break</p>
如果要编写格式正确的XMLHTML,请遵循万维网联盟(W3C)的可扩展超文本标记语言(XHTML)标准。 所有现代浏览器都呈现XHTML。 另外,可以使用XML工具读取XHTML并在文档中查找数据,这比通过HTML解析要容易得多。
使用DOM库读取XML
读取格式正确的XML文件的最简单方法是使用编译为某些PHP安装中的文档对象模型(DOM)库。 DOM库将整个XML文档读入内存并将其表示为节点树,如图1所示。
图1.书籍XML的XML DOM树
树顶部的books
节点具有两个子book
标签。 每本书中都有author
, publisher
和title
节点。 author
, publisher
和title
节点每个都有包含文本的子文本节点。
清单2显示了读取书籍XML文件并使用DOM显示内容的代码。
清单2.使用DOM阅读XML
<?php
$doc = new DOMDocument();
$doc->load( 'books.xml' );
$books = $doc->getElementsByTagName( "book" );
foreach( $books as $book )
{
$authors = $book->getElementsByTagName( "author" );
$author = $authors->item(0)->nodeValue;
$publishers = $book->getElementsByTagName( "publisher" );
$publisher = $publishers->item(0)->nodeValue;
$titles = $book->getElementsByTagName( "title" );
$title = $titles->item(0)->nodeValue;
echo "$title - $author - $publisher\n";
}
?>
该脚本首先创建一个new DOMdocument
对象,然后使用load
方法将书籍XML加载到该对象中。 之后,脚本使用getElementsByName
方法获取具有给定名称的所有元素的列表。
在book
节点的循环内,脚本使用getElementsByName
方法获取author
, publisher
和title
标签的nodeValue
。 nodeValue
是节点内的文本。 然后,脚本将显示这些值。
您可以在命令行上运行PHP脚本,如下所示:
% php e1.php
PHP Hacks - Jack Herrington - O'Reilly
Podcasting Hacks - Jack Herrington - O'Reilly
%
如您所见,每个书芯都会打印一行。 这是一个好的开始。 但是,如果您无权访问XML DOM库怎么办?
使用SAX解析器读取XML
读取XML的另一种方法是使用XML的简单API(SAX)解析器。 PHP的大多数安装都包括SAX解析器。 SAX解析器在回调模型上运行。 每次打开或关闭标签时,或者每当解析器看到一些文本时,它都会使用节点或文本信息对某些用户定义的函数进行回调。
SAX解析器的优点是它非常轻巧。 解析器不会在内存中保留任何内容很长时间,因此可以用于超大文件。 缺点是编写SAX解析器回调很麻烦。 清单3显示了读取书籍XML文件并使用SAX显示内容的代码。
清单3.使用SAX解析器阅读XML
<?php
$g_books = array();
$g_elem = null;
function startElement( $parser, $name, $attrs )
{
global $g_books, $g_elem;
if ( $name == 'BOOK' ) $g_books []= array();
$g_elem = $name;
}
function endElement( $parser, $name )
{
global $g_elem;
$g_elem = null;
}
function textData( $parser, $text )
{
global $g_books, $g_elem;
if ( $g_elem == 'AUTHOR' ||
$g_elem == 'PUBLISHER' ||
$g_elem == 'TITLE' )
{
$g_books[ count( $g_books ) - 1 ][ $g_elem ] = $text;
}
}
$parser = xml_parser_create();
xml_set_element_handler( $parser, "startElement", "endElement" );
xml_set_character_data_handler( $parser, "textData" );
$f = fopen( 'books.xml', 'r' );
while( $data = fread( $f, 4096 ) )
{
xml_parse( $parser, $data );
}
xml_parser_free( $parser );
foreach( $g_books as $book )
{
echo $book['TITLE']." - ".$book['AUTHOR']." - ";
echo $book['PUBLISHER']."\n";
}
?>
该脚本首先设置g_books
数组和g_elem
变量,该数组将所有书籍及其信息保存在内存中,该变量存储脚本当前正在处理的标签的名称。 然后,脚本定义了回调函数。 在此示例中,回调函数为startElement
, endElement
和textData
。 分别在打开和关闭标签时调用startElement
和endElement
函数。 在标签开始和结束之间的文本上调用textData
函数。
在此示例中, startElement
标记正在寻找book
标记以启动book
数组中的新元素。 然后, textData
函数查看当前元素以查看它是publisher
, title
还是author
标记。 如果是这样,该函数会将当前文本放入当前书中。
为了进行解析,脚本使用xml_parser_create
函数创建了解析器。 然后,它设置回调处理程序。 之后,脚本读取文件并将文件的大块发送给解析器。 读取文件后, xml_parser_free
函数删除解析器。 脚本的末尾转储g_books
数组的内容。
如您所见,这比DOM等效代码要难得多。 如果您没有DOM库或SAX库怎么办? 还有其他选择吗?
使用正则表达式解析XML
我肯定会提到某些方法而受到某些工程师的抨击,但是您可以使用正则表达式解析XML。 清单4显示了一个使用preg_
函数读取books文件的示例。
清单4.阅读带有正则表达式的XML
<?php
$xml = "";
$f = fopen( 'books.xml', 'r' );
while( $data = fread( $f, 4096 ) ) { $xml .= $data; }
fclose( $f );
preg_match_all( "/\<book\>(.*?)\<\/book\>/s",
$xml, $bookblocks );
foreach( $bookblocks[1] as $block )
{
preg_match_all( "/\<author\>(.*?)\<\/author\>/",
$block, $author );
preg_match_all( "/\<title\>(.*?)\<\/title\>/",
$block, $title );
preg_match_all( "/\<publisher\>(.*?)\<\/publisher\>/",
$block, $publisher );
echo( $title[1][0]." - ".$author[1][0]." - ".
$publisher[1][0]."\n" );
}
?>
注意该代码有多短。 首先将文件读取为一个大字符串。 然后,它使用一个regex
函数读取每个书本。 最终,脚本使用foreach
循环,在每个书芯周围循环,并挑选出作者,书名和出版商。
那么,缺点是什么呢? 使用正则表达式代码读取XML的问题在于,它不会首先检查以确保XML格式正确。 这意味着在开始阅读XML之前,您可能不知道自己的XML格式不正确。 另外,某些有效形式的XML可能与您的正则表达式不匹配,因此您稍后必须对其进行修改。
我从不建议使用正则表达式来读取XML,但有时这是最兼容的方式,因为正则表达式函数始终可用。 不要使用正则表达式来读取直接来自用户的XML。 您无法控制该XML的形式或结构。 始终使用DOM库或SAX解析器从用户读取XML。
用DOM编写XML
读取XML只是方程式的一部分。 怎么写呢? 编写XML的最好方法是使用DOM。 清单5显示了DOM如何构建书籍XML文件。
清单5.用DOM编写XML书籍
<?php
$books = array();
$books [] = array(
'title' => 'PHP Hacks',
'author' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
$books [] = array(
'title' => 'Podcasting Hacks',
'author' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
$doc = new DOMDocument();
$doc->formatOutput = true;
$r = $doc->createElement( "books" );
$doc->appendChild( $r );
foreach( $books as $book )
{
$b = $doc->createElement( "book" );
$author = $doc->createElement( "author" );
$author->appendChild(
$doc->createTextNode( $book['author'] )
);
$b->appendChild( $author );
$title = $doc->createElement( "title" );
$title->appendChild(
$doc->createTextNode( $book['title'] )
);
$b->appendChild( $title );
$publisher = $doc->createElement( "publisher" );
$publisher->appendChild(
$doc->createTextNode( $book['publisher'] )
);
$b->appendChild( $publisher );
$r->appendChild( $b );
}
echo $doc->saveXML();
?>
在脚本的顶部, books
数组中装有一些示例书。 该数据可能来自用户或数据库。
加载示例书籍后,脚本将创建一个new DOMDocument
并将根books
节点添加到其中。 然后,脚本为每本书的作者,标题和出版者创建一个元素,并向每个节点添加一个文本节点。 每个工作book
节点的最后一步是将其重新连接到根工作books
节点。
脚本的末尾使用saveXML
方法将XML转储到控制台。 (您还可以使用save
方法从XML创建文件。)脚本的输出如清单6所示。
清单6. DOM构建脚本的输出
% php e4.php
<?xml version="1.0"?>
<books>
<book>
<author>Jack Herrington</author>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>Podcasting Hacks</title>
<publisher>O'Reilly</publisher>
</book>
</books>
%
使用DOM的真正价值在于它创建的XML总是格式正确的。 但是,如果您无权访问DOM来创建XML,该怎么办?
用PHP编写XML
如果DOM不可用,则可以使用PHP文本模板编写XML。 清单7显示了PHP如何构建书籍XML文件。
清单7.用PHP编写XML书籍
<?php
$books = array();
$books [] = array(
'title' => 'PHP Hacks',
'author' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
$books [] = array(
'title' => 'Podcasting Hacks',
'author' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
?>
<books>
<?php
foreach( $books as $book )
{
?>
<book>
<title><?php echo( $book['title'] ); ?></title>
<author><?php echo( $book['author'] ); ?>
</author>
<publisher><?php echo( $book['publisher'] ); ?>
</publisher>
</book>
<?php
}
?>
</books>
该脚本的顶部类似于DOM脚本。 脚本的底部打开books
标签,然后遍历每本书,创建book
标签以及所有内部title
, author
和publisher
标签。
这种方法的问题是对实体进行编码。 为了确保实体正确编码,必须在每个项目上调用htmlentities
函数,如清单8所示。
清单8.使用htmlentities函数编码实体
<books>
<?php
foreach( $books as $book )
{
$title = htmlentities( $book['title'], ENT_QUOTES );
$author = htmlentities( $book['author'], ENT_QUOTES );
$publisher = htmlentities( $book['publisher'], ENT_QUOTES );
?>
<book>
<title><?php echo( $title ); ?></title>
<author><?php echo( $author ); ?> </author>
<publisher><?php echo( $publisher ); ?>
</publisher>
</book>
<?php
}
?>
</books>
这就是为什么用基本PHP编写XML很烦人的原因。 您认为自己正在创建完美的XML,但是随后发现当您尝试通过XML运行数据时,某些元素的编码不正确。
结论
XML一直围绕着它大肆宣传和混乱。 但是,这并不像您想象的那么难,特别是在像PHP这样的出色语言中。 正确理解和实现XML后,您会发现可以使用许多强大的工具。 XPath和XSLT是两个值得一试的工具。
翻译自: https://www.ibm.com/developerworks/xml/library/os-xmldomphp/index.html
java dom读写xml