📄 xmlstarlet 使用入门 - fanqiang_com.htm
字号:
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>现在更简洁了,清单中只剩下了文件,文件节点中只能看到文件的大小和名称。为了更便于跟踪,可以将结果保存在一个名为 ls.xml
的文件中。也可使用 <CODE>rename</CODE> 编辑函数将 <CODE>f</CODE> 标签修改为
<CODE>file</CODE>(如清单 6 所示)。 </P><A name=code6><B>清单 6.
显示大小和文件名属性的目录列表</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% cat ls.xml | xml ed -r "//f" -v "file"
<?xml version="1.0"?>
<xml>
<file s="6148" n=".DS_Store"/>
<file s="173" n="build.xml"/>
<file s="641" n="input.xml"/>
<file s="3587" n="main.xsl"/>
<file s="184" n="Makefile"/>
<file s="3869" n="MyGenerator.class"/>
<file s="5265" n="MyGenerator.java"/>
</xml>
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>此外,如果标签和属性不愿意使用短名字如 <CODE>s</CODE> 和 <CODE>n</CODE>,可以分别将其修改为
<CODE>size</CODE> 和 <CODE>name</CODE>(如图 7 所示)。</P><A
name=code7><B>清单 7. 使用 file 标签的目录列表</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% cat ls.xml | xml ed -r "//f" -v "file" -r "//@s" -v "size" -r "//@n" -v "name"
<?xml version="1.0"?>
<xml>
<file size="6148" name=".DS_Store"/>
<file size="173" name="build.xml"/>
<file size="641" name="input.xml"/>
<file size="3587" name="main.xsl"/>
<file size="184" name="Makefile"/>
<file size="3869" name="MyGenerator.class"/>
<file size="5265" name="MyGenerator.java"/>
</xml>
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这样读起来更容易了。到现在还没有写一行 XSLT、Perl 或 Java 代码。将该文件保存为 ls2.xml。</P>
<P><A name=IDA1ZHKB><SPAN
class=atitle2>验证</SPAN></A><BR>新的目录列表看起来不错,那么是不是仍然有效呢?清单 8
说明了如何来进行判断。</P><A name=code8><B>清单 8. 检查 XML 的良构性</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% xml val ls2.xml
ls2.xml - valid
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>啊,是有效的。就是说它是结构良好的,即标签是平衡的、字符编码是正确的等等。但是仍然可能缺少必要的标签或者正确的标签。为此必须知道文件的正确结构,因此需要一个模式。只有用模式检查
XML 文档并且通过之后才能说它是有效的。</P>
<P>清单 9 显示了 XML 目录列表文件的基本 RELAX NG 模式。</P><A name=code9><B>清单 9.
RELAX NG 模式</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
<?xml version="1.0" encoding="UTF-8"?>
<grammar ns="" xmlns=http://relaxng.org/ns/structure/1.0
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<element name="xml">
<oneOrMore>
<element name="file">
<attribute name="name">
<data type="NMTOKEN"/>
</attribute>
<attribute name="size">
<data type="integer"/>
</attribute>
</element>
</oneOrMore>
</element>
</start>
</grammar>
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>RELAX NG 读起来很容易。最上面的 <CODE>element</CODE> 标签定义了 <CODE>xml</CODE>
作为基本标签。然后,<CODE>xml</CODE> 标签中的 <CODE>oneOrMore</CODE> 标签被命名为
<CODE>file</CODE> 和 <CODE>size</CODE>。</P>
<P>ls2.xml 文件对于这个新的模式有效吗?请参阅清单 10。</P><A name=code10><B>清单 10.
用模式检查</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% xml val -e -r ls.rng ls2.xml
ls2.xml - valid
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>如果您像我一样 —— 只有看到错误才会满足,那么可以在 ls3.xml 文件中的一个文件节点中添加属性
<CODE>someAttribute</CODE>,然后再检查该文件(参见清单 11)。</P><A
name=code11><B>清单 11. 用模式检查错误的文件</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% xml val -e -r ls.rng ls3.xml
ls3.xml:4: element file: Relax-NG validity error :
» Invalid attribute someAttribute for element file
ls3.xml - invalid
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>结果证明失败了。不但要知道文件是结构良好的,还要知道所有的标签和属性都是正确的。</P>
<P><A name=IDAQ2HKB><SPAN class=atitle2>文本</SPAN></A><BR>还可以使用选择函数从
XML 提取数据元素。清单 12 中的例子从 XML 目录中提取文件名作为普通文本。</P><A name=code12><B>清单
12. 提取文件名</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% xml sel -t -m "/xml/file" -v "concat(@name,'&#10;')" ls2.xml
.DS_Store
build.xml
input.xml
main.xsl
Makefile
MyGenerator.class
MyGenerator.java
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这里要注意两点。首先,提取文件名的 XPath 是 <CODE>/xml/file</CODE> 条款。其次使用
<CODE>-v</CODE> 选项的输出说名用回车换行连接 <CODE>file</CODE> 标签中的
<CODE>name</CODE> 属性。</P>
<P>现在增加 <CODE>-s</CODE> 选项,按照 <CODE>size</CODE> 属性对文件排序(参见清单 13)。
<CODE>A:N:-</CODE> 语法告诉 XMLStarlet 按照数值大小递增排序。(这里将 <CODE>size</CODE>
参数添加到 <CODE>concat</CODE> 语句中以便能正常工作。)</P><A name=code13><B>清单 13.
列表排序</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% xml sel -t -m "/xml/file" -s A:N:- "@size" -v "concat
» ( @name,':',@size,'&#10;' ) " ls2.xml
build.xml:173
Makefile:184
input.xml:641
main.xsl:3587
MyGenerator.class:3869
MyGenerator.java:5265
.DS_Store:6148
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=IDAZ4HKB><SPAN class=atitle2>牛刀小试</SPAN></A><BR>为了让
<CODE>xml</CODE> 命令做点实际工作,可以使用它解析一份交通报告。 Yahoo!® Maps 提供了交通服务,可以使用
<CODE>curl</CODE> 命令和 <CODE>-g</CODE> 选项(表示 <I
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">GET</I>)通过 RSS
下载最新的交通信息。比如在清单 14 中,通过添加 <CODE>?csz=94101</CODE>
参数指定了我的邮政编码,于是得到了旧金山最新的交通报告。</P><A name=code14><B>清单 14.
旧金山的交通报告(RSS)</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% curl -g "http://maps.yahoo.com/traffic.rss?csz=94101" –s
<?xml version="1.0" encoding="ISO-8859-1" ?>
<rss version="2.0">
<channel>
<title>Yahoo! Maps Traffic -- San Francisco, CA 94101</title>
<link>http://us.rd.yahoo.com/maps/mapresults/trfrssarea/*
» http://maps.yahoo.com/maps_result?csz=
» San+Francisco%2C++CA+94101&amp;country=
» us&amp;lat=37.775&amp;lon=
» -122.4183&amp;trf=1&amp;mag=5</link>
<category>Traffic</category>
<description>Yahoo! Maps Traffic --
» San Francisco, CA 94101</description>
<language>en-us</language>
<ttl>3</ttl>
<lastBuildDate>Fri, 06 May 2005 16:33:59 -0700<
» /lastBuildDate>
<pubDate>Fri, 06 May 2005 18:31:27 CDT<
» /pubDate>
<copyright>Copyright (c) 2005 Yahoo! Inc.
» All rights reserved.</copyright>
<item>
<title>
Incident, On I-580 At Seminary Ave
</title>
<description>
Traffic Collision, Severity: Major, Started: 04:20pm 05/06/05,
» Estimated End: 04:50pm 05/06/05,
» Last Updated: 04:25pm 05/06/05
</description>
<link>http://us.rd.yahoo.com/maps/mapresults/trfrssitem/*
» http://maps.yahoo.com/maps_result?csz=
» San+Francisco%2C++CA+94101&amp;mlt=
» 37.778234&amp;mln=-122.168438&amp;lat=
» 37.775&amp;lon=-122.4183&amp;trf=
» 1&amp;exctrf=1&amp;mag=4</link>
<pubDate>Fri, 06 May 2005 16:20:00 -0700</pubDate>
<category>Incident </category>
<severity>Major</severity>
<endDate>Fri, 06 May 2005 16:50:00 -0700</endDate>
<updatedDate>Fri, 06 May 2005 16:25:00 -0700<
» /updatedDate>
</item>
...
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>现在可以将 <CODE>curl</CODE> 命令的输出通过 XMLStarlet 命令去除其中的描述部分(如清单 15
所示)。</P><A name=code15><B>清单 15. 通过 XMLStarlet 处理的交通 RSS</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
% curl -g "http://maps.yahoo.com/traffic.rss?csz=94101"
» -s | xml sel -t -m "/rss/channel/item/description" -v "."
Traffic Collision, Severity: Major, Started: 04:20pm 05/06/05,
» Estimated End: 04:50pm 05/06/05,
» Last Updated: 04:25pm 05/06/05
Disabled Vehicle, Severity: Moderate, Started: 04:20pm 05/06/05,
» Estimated End: 04:50pm 05/06/05,
» Last Updated: 04:25pm 05/06/05
Disabled Vehicle, Severity: Moderate, Started: 04:19pm 05/06/05,
» Estimated End: 04:49pm 05/06/05,
» Last Updated: 04:25pm 05/06/05
Pedestrian On The Roadway, Severity: Critical,
» Started: 04:17pm 05/06/05,
» Estimated End: 04:47pm 05/06/05,
» Last Updated: 04:25pm 05/06/05
Traffic Collision, Severity: Major, Started: 04:15pm 05/06/05,
» Estimated End: 04:45pm 05/06/05,
» Last Updated: 04:25pm 05/06/05
...
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><CODE>-m</CODE> 选项从每个项中取出描述,然后使用 <CODE>-v</CODE>
选项通过句点(<CODE>.</CODE>)输出节点中的文本。</P>
<P><A name=IDACBIKB><SPAN
class=atitle2>结束语</SPAN></A><BR>本文粗略地介绍了这种强大的 XML 工具。有时间的话,不妨试一试
XMLStarlet 的 XSLT 转换功能、方便的转义和取消转义功能以及 XML
格式化功能等等。</P><!-- 正文end --><BR>(http://www.fanqiang.com)<BR></FONT><BR><FONT
color=#999999><SMALL>原文链接:<A
href="http://www-128.ibm.com/developerworks/cn/xml/x-starlet.html"
target=_blank>http://www-128.ibm.com/developerworks/cn/xml/x-starlet.html</A></SMALL></FONT>
<BR></FONT></TD></TR></TBODY></TABLE><BR></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=750 border=0>
<TBODY>
<TR>
<TD align=middle width=620>
<TABLE cellSpacing=0 cellPadding=0 width=562 border=0>
<TBODY>
<TR>
<TD width=562>
<TABLE cellSpacing=0 cellPadding=0 width=562 border=0>
<TBODY>
<TR>
<TD>
<TABLE cellSpacing=1 cellPadding=5 width="100%" border=0>
<TBODY>
<TR>
<TD class=f14 bgColor=#666666><B><FONT color=#ffffff
size=2> <B>相关文章</B></FONT></B></TD></TR>
<TR>
<TD
class=f14><BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD height=10></TD></TR></TBODY></TABLE><!--结束:底部-->
<TABLE width=750 border=0>
<TBODY>
<TR>
<TD width="100%" bgColor=#d09f0d colSpan=5 height=2><IMG height=1
src="XMLStarlet 使用入门 - fanqiang_com.files/c.gif" width=1></TD></TR>
<TR>
<TD vAlign=top width="100%" colSpan=5 height=40>
<P align=center><FONT
color=#ffffff>★ 感谢所有的作者为我们学习技术知识提供了一条捷径 ★
<BR>www.fanqiang.com</FONT></P></TD></TR></TBODY></TABLE>
<CENTER></CENTER></TR></TBODY></TABLE></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -