XML数据处理杂记
XML之所以应用广泛应该是因为其通用性,Web service、跨平台数据转换等经常采用XML格式。最近采用XML作为中间格式实现了一个较大数据量的迁移(与下面示例无关),在此总结一下大致用法,当然这里只涉及XML相关的部分,忽略了sed, awk之类的辅助工具。希望您能指出用法的不当之处,或更好的方法。
1. XML Schema – 定义数据结构
XML Schema与DTD类似,都是用于定义XML文档结构,但比DTD更加灵活、更加强大。有趣的是XSD其本身也采用XML描述,因此XSD的结构是用DTD来定义(http://www.w3.org/2001/XMLSchema.dtd)。
blog_post.xsd示例文档:
<?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns="http://tangobean.com" xmlns:fwso="http://tangobean.com" elementFormDefault="qualified" targetNamespace="http://tangobean.com" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="posts"> <xs:complexType> <xs:sequence minOccurs="0" maxOccurs="unbounded"> <xs:element name="post" type="blogPost" /> </xs:sequence> </xs:complexType> <xs:unique name="uniqueIssueID"> <xs:selector xpath="fwso:post" /> <xs:field xpath="fwso:id" /> </xs:unique> </xs:element> <xs:complexType name="blogPost"> <xs:sequence> <xs:element name="id" type="xs:integer" /> <xs:element name="title" type="xs:string" /> <xs:element name="author" type="xs:string" /> <xs:element name="body" type="xs:string" /> <xs:element name="publish_time" type="timestamp" /> <xs:element name="tags" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence minOccurs="0" maxOccurs="unbounded"> <xs:element name="tag" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:simpleType name="timestamp"> <xs:restriction base="xs:string"> <xs:pattern value="[1-9][0-9]{9}" /> </xs:restriction> </xs:simpleType> </xs:schema>
该XSD定义了一个简单的博客文章的结构,integer, string等类型是XSD定义的数据类型,XSD可以自定义数据类型,如该示例中的timestamp。
2. xmllint – XML文档验证
xmllint事实上是一个XML解析工具,可以用于XML文档格式验证、格式化等。这里使用xmllint来验证XML文档是否符合XSD的定义:
xmllint -noout -schema blog_post.xsd posts.xml
如果验证通过,则会输出:
posts.xml validates
否则会输出对应的错误,类似:
posts.xml:11: element newtag: Schemas validity error : Element '{http://tangobean.com}newtag': This element is not expected. Expected is ( {http://tangobean.com}tags ). posts.xml:13: element post: Schemas validity error : Element '{http://tangobean.com}post': Duplicate key-sequence ['210'] in unique identity-constraint '{http://tangobean.com}uniqueIssueID'. posts.xml fails to validate
post.xml示例内容如下:
<?xml version="1.0"?> <posts xmlns="http://tangobean.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tangobean.com blog_post.xsd"> <post> <id>210</id> <title>blog post 1</title> <author>James Tang</author> <body><![CDATA[<h1>what's this</h1><p>goes here</p>]]></body> <publish_time>1346221680</publish_time> <newtag>hello</newtag> </post> <post> <id>210</id> <title>blog post 2</title> <author>James Tang</author> <body><![CDATA[<h1>what's this</h1><p>goes here</p>]]></body> <publish_time>1346221680</publish_time> <tags> <tag>tag1</tag> <tag>tag2</tag> </tags> </post> </posts>
3. xQeury – 转换数据
xQuery能够非常方便地将其它格式的XML文档转换成目标的XML格式。
blog_post.xquery示例如下:
xquery version "1.0"; declare default element namespace "http://tangobean.com" declare namespace fwso="http://tangobean.com"; declare variable $fwso:oldDoc as xs:string := "olddoc.xml"; declare variable $fwso:oldTagDoc as xs:string := "oldtagdoc.xml"; declare function fwso:list-posts($maindoc as xs:string, $tagdoc as xs:string) { let $doc := doc($maindoc) let $seq := $doc//article let $tags := doc($tagdoc) for $item in $seq let $id := data($item/article_id) let $ptags := $tags//tag[article_id=$id] return <post> <id>{$id}</id> <title>{data($item/article_title)}</title> <author>{data($item/article_author)}</author> <body>{data($item/article_content)}</body> <publish_time>{data($item/published)}</publish_time> {if (count($ptags) gt 0) then <tags> {for $tag in $ptags return <tag>{data($tag/tag_name)}</tag> } </tags> else '' } </post> }; <posts xmlns="http://tangobean.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tangobean.com blog_post.xsd" > {fwso:list-posts($fwso:oldDoc, $fwso:oldTagDoc)} </posts>
4. XQilla/Zorba – xQuery解析器
xqilla blog_post.xquery > posts.xml
或
zorba -f -q blog_post.xquery > posts.xml
5. 参考
- http://www.w3.org/TR/xmlschema11-1/
- http://www.w3.org/TR/xmlschema11-2/
- http://www.w3.org/TR/xquery/
- http://www.zorba-xquery.com/html/index
- http://xqilla.sourceforge.net/HomePage