|
|
|
|
 XML 版本周的翻译计划 (5月24日) - dlee [ 2001-05-24 16:38 | 906 byte(s)]
 翻译稿:使用 Jena 处理 RSS 1.0 - dlee [ 2001-05-26 21:46 | 4,603 byte(s)]
 翻译稿:使用 Jena API 处理 RDF - dlee [ 2001-05-26 16:59 | 8,591 byte(s)]
 翻译稿:XML 和配置文件 - dlee [ 2001-05-24 21:45 | 10,937 byte(s)]
|
|
|
|
[Original]
[Print]
[Top]
|
XML 和配置文件
作者:Joe "Zonker" Brockmeier
发表时间:2001年2月
原文链接: http://www.performancecomputing.com/columns/zonker/zonker0201.shtml
译者:dlee
翻译时间:2001年5月24日
上个月,我写了关于 XML 的奇迹和它能够怎样给系统管理员带来好处。这是一个很广泛的话题,我相信比我更好的头脑可以想出一些其它的方法来实现有趣的 time-savers (节省时间的好工具 -- 译者注) 和我尚未考虑到的解决方案。
这个月,我要看一下使用 XML 来做配置文件。你知道,在 /etc 下或其它某个地方的那些讨厌的文件每个都有其自己的格式。虽然这些文件都为一个目的服务,但是写一个可以与多个文件共同工作的任何类型的集中管理程序都非常困难。我们大多数使用 Linux 或其它 Unix 的人都避免使用 configuration wizards (配置向导 -- 译者注) 和用于系统管理的 GUI 工具。尽管如此,易用的配置工具对于把 Linux 带向一个新的层次是需要的。当然这并不意味着我们必须使用它们,这仅仅意味着必须有这样的工具。
我将看看一个简单的用于 Linux 配置文件的 XML Schema。上个月,我说使用一个 DTD 来做这个工作。但是在这期间我看了一下 XML Schema 的建议,我确信使用 Schema 是更好的方法。
一段关于 DTD 和 Schema 的迅速讨论:
DTD 和 Schema 之间的区别是什么?首先,DTD 并不是真正的 native XML (XML 土著 -- 译者注),DTD 是一个 SGML 的遗留物,它们对于出版业是非常出色的。然而 DTD 对于在 Web 上共享数据 (XML 最初的目的) 是不够的,因为它不允许定义正确的数据类型 (proper data types)。只有极少的数据类型可以在一个 DTD 中定义,但是它们对于编程或者做类似的事并非真正有用。而 Schema 被设计用来处理通常的数据类型,并且允许通常的数据类型组合成为新的数据类型。
一段简短和差劲的关于 XML Schema 的解释,来自于 W3C 的网站 (这只是作者的观点 -- 译者注):
XML Schema 定义了共享的标记词汇表和允许机器执行的由人所定义的规则,它提供了一个定义 XML 文档的结构,内容和语义的方法。
所以,确切地说,我们正在寻找的是 -- 一些给我们的配置文件带来结构的东西。
让我们看一下一个所有系统管理员可能都熟记于心的配置文件 /etc/fstab
我的 /etc/fstab 看起来是这样的:
/dev/hda1 swap swap defaults 0 0
/dev/hda2 / ext2 defaults 1 1
/dev/hda3 /home ext2 defaults 1 1
/dev/hda4 /files ext2 defaults 1 1
none /dev/pts devpts gid=5,mode=620 0 0
none /proc proc defaults 0 0
现在,这个文件相当丑陋。不仅丑陋,而且它没有真正告诉我关于文件中数据的任何事情。
确实,通常的系统管理员知道这个文件中包含了什么,并且不需要任何指导,但是如果你是一个 Linux 的新用户呢?从 NT 迁移到 Linux 上的人当看到这个文件时总是希望有 GUI 的支持。并且,我要注解的是,这还只是 Linux 上一个简单的配置文件,当配置 Sendmail 的配置文件时,那才是他们哭的时候呢。也许不至于,但是确实不好处理。
顺便说一句,我并没有试图使用 Unix 的方法来做这件事,对于现存的方法,我在任何一天都将优先采用 Unix (或 Linux)的方法,而不是 Windows 的注册表或者 MacOS 的方法。尽管如此,还是总是有改进的余地的。
现在,另一方面,这个文件作为一个 XML 文档看起来将是这样:
< ?xml version="1.0">
< fstab>
< fs_spec file="none" vfstype="swap" dump="0" passno="0" block="hda1"
< fs_mntops/>
< /fs_spec>
< fs_spec file="/" vfstype="ext2" dump="1" passno="1" block="hda2"/>
< fs_mntops/>
< /fs_spec>
< fs_spec file="home" vfstype="ext2" dump="1" passno="1" block="hda3"/>
< fs_mntops/>
< /fs_spec>
< fs_spec file="files" vfstype="ext2" dump="1" passno="1" block="hda4"/>
< fs_mntops/>
< /fs_spec>
< fs_spec file="dev/pts" vfstype="ext2" dump="0" passno="0" block="none"/>
< fs_mntops gid="5" mode="620"/>
< /fs_spec>
< fs_spec file="proc" vfstype="proc" dump="0" passno="0" block="none"/>
< fs_mntops/>
< /fs_spec>
< /fstab>
这个文件里描述的信息就比最初的 fstab 多了很多。如果我选择不同的元素名和属性名,描述的信息甚至会更多。尽管如此,我还是尽量保持现有 (fstab 中的) 的命名约定。mount,umount,dump 和 fsck 都会读 fstab 得到它们想要得数据。如果有人试图真正为这些程序实现一个 XML 配置文件,属性名现有的名字将会使事情简单许多。
与试图用不同的列分开各个值,并且希望记住字段 5 由 dump 读取,字段 6 由 fsck 读取不同,这里我有属性 “dump” (相当容易记住) 和 fsck 使用的“passno”(不太容易记住)。它们以哪个顺序出现并没有关系,只要它们被包含进去了。这给我带来了 XML 的另一个优点。如果你是一个新的或者健忘的系统管理员。你试图修改或添加一个条目到 fstab 文件中,并且输入了一个非法值或做了其它什么把事情搞糟了,这将带来可怕的后果。然而,使用 Schema 来验证一个配置文件能够避免这些错误。任何一个使用这个文件的管理程序能够读取这个 Schema,于是如果你试图输入非法值或使某个字段为空的时候,管理程序将防止新的文件被写入,并且指出这个错误。这不是比以后遇到一大堆令人恶心的错误要好吗?
注意,当修改这个文件时,实现任何类型的 GUI wizard 或外部应用程序并不是必需的,如果这不是你的风格的话。一个验证的解析器 (例如 Xerces -- 译者注) 能够简单地检查 fstab.xml 文件并且在控制台显示任何错误。就象 Jade 在你验证一个 DocBook SGML 文件时所做的那样。如果没有错误,程序没有输出或者简单地给出一个 “file valid” 响应,如果有错误,程序将返回错误类型和行号。
现在我讨论过了 XML Schema 的优点,让我们看一个用于这个文件的一个简单的 XML Schema:
< xsd:schema xmlns:xsd="http://www.w3.org/2000/08/XMLSchema">
< xsd:annotation>
< xsd:documentation>
This is a comment/documentation
You can actually embed documentation into a Schema.
< /xsd:documentation>
< /xsd:annotation>
< xsd:element name="fstab" type="fstabType"/>
< xsd:complexType name="fstabType">
< xsd:sequence>
< xsd:element name="fs_spec" minOccurs="1" type="specType"/>
< xsd:element name="fs_mntops" type="mntopsType"/>
< /xsd:sequence>
< /xsd:complexType>
< xsd:complexType name="specType">
< attribute name="file" minOccurs="1" maxOccurs="1" type="xsd:string"/>
< attribute name="vfstype" minOccurs="1" maxOccurs="1" type="xsd:string"/>
< attribute name="dump" minOccurs="1" maxOccurs="1" type="xsd:decimal"/>
< attribute name="passno" minOccurs="1" maxOccurs="1" type="xsd:decimal"/>
< attribute name="block" minOccurs="1" maxOccurs="1" type="xsd:string"/>
< /xsd:complexType>
< xsd:complexType name="mntopsType">
< attribute name="gid" minOccurs="0" type="xsd:decimal"/>
< attribute name="mode" minOccurs="0" type="xsd:decimal"/>
< /xsd:complexType>
< /xsd:schema>
这个文件看起来很复杂,但实际上不是。这个文件有些冗长,但是并不困难。这个 Schema 为一个文件和它的属性定义了合法的元素,它还定义了一个文件的语法,陈述了哪个元素需要在其它元素中出现,哪个元素必须有属性,哪个元素可以有也可以没有属性。你将注意到这个 Schema 也有一个注解 (< xsd:annotation>) 和文档 (< xsd:documentation>) 元素。Schema 是一种 Self-documenting 的文档,它们并没有写出关于它们自身的文档,但是它们确实允许文档被嵌入到它们自身当中。所以,当一个程序员写一个 Schema 时,他能够把这些当作注释,通过一个正确的样式单,Schema 能够被处理并只显示出文档 (< xsd:documentation>) 和注解 (< xsd:annotation>) 所包含的内容。
这个 Schema 也定义了一个复杂的元素,这个元素由多个其它元素组成 (或者说包含多个其它元素)。整个的 fstab 配置文件成为一个元素类型,所以理论上,整个系统范围的配置能够被包含到一个文件中,而不是有一个叫做 etc 的目录。你可以有一个名为 etc.xml 的文件包含了象 fstab,mailcap,printcap 这一类的元素。使用这个 Schema,你也有机会要求一个属性,文件除非有这个属性存在,并且只能有你所定义类型的值,否则文件就是非法的。实际上的结果是你能够避免 fstab 在没有一个为 block devices 设置的 “vfstype”属性时被改写。你甚至可以定义一个 “vfstype”的合法值列表来避免当文件中含有 vfstype 的非法值时被改写或者使用。
对于这个想法有一些 rough edges 是无疑的 (我觉得实现起来并不是太难 -- 译者注),但是我希望这能够给你带来一些思考。Unix 的哲学 -- 总的说来是一个操作系统的最佳设计模式 -- 至少是我见过的最佳的模式。尽管如此,我认为不同的配置文件的聚集是混乱的并将导致很多级别上的重复努力。在同一个结构和语法上巩固和标准化这些配置文件是一件很好的事情。
下个月我将离开 XML,讨论一些新的和令人兴奋的事 -- 使用 iptables (ipchains 的替代者) 来做包过滤。
资源:
W3C's Schema Primer -- 你想知道的关于 XML Schema 的所有事情.
Web XML Schema Validator --在线验证你的 XML Schema
Perl DTD to XML Schema Conversion Tool --如果你使用 DTD,但希望移植到 XML Schema,这个工具将为你做一些事情
Schema Structures
Schema Datatypes
XML in 10 points -- (实际上是7点...)
Extensible Markup Language (XML)
XHTML 1.0
DocBook.org
The XML Cover Pages
正式的翻译稿 (html 文件) 我贴在附件里,大家可以下载下来看。
--dlee
有人说一个人有烦恼是因为记性太好。那年开始,我忘记了很多事情,唯一有印象的,就是我喜欢桃花。
|
|
|
--
|
|
[Original]
[Print]
[Top]
|
|
[Original]
[Print]
[Top]
|
使用 Jena API 处理 RDF
作者:Joe Verzulli
发表时间:2001年5月23日
原文链接:http://www.xml.com/pub/a/2001/05/23/jena.html
译者:dlee
翻译时间:2001年5月26日
对于 RDF (资源定义框架) 的兴趣正在日渐增长,很多用于处理 RDF 的工具和开发库已经被开发出来。这篇文章描述了一个这样的开发库,Jena,用于处理 RDF 的一套 Java API,它也是一个实现这套 API 的开放源码软件的名字。
什么是 RDF?
XML 非常灵活,它允许信息以很多种不同的方式来编码。如果使用有意义的标记,对于人来确定一个 XML 字符串的含义就会相对容易。尽管如此,对于程序来说确定一个 XML 字符串的含义仍然是困难的,因为程序并不懂得英文的标记名。DTD 和 XML Schema 对于这一问题并非真正有帮助,它们只是允许一个程序来验证一个 XML 字符串是否符合某个规则集合。
RDF (RDFMS ,Bray, Ogbuji,SWARDF) 是一个以一种允许程序懂得文档意图表现的含义的方式来表现信息的模型和 XML 语法。它建立在一个 statement,即具有形式{predicate, subject, object} 的一个三元组的概念之上。对于一个三元组的解释是 < subject> 有一个属性 < predicate>,属性值是 < object>。statement 的例子是 {numberOfHits, http://www.foo.com/index.html, 3000} 和 {title, http://bookstore.com/book12, "The Connoisseur's Guide to the Mind"}。在 RDF 中一个 总是一个以 URL 来命名的资源,这个 URL 有一个可选的锚 id。< predicate> 是资源的一个属性,< object> 是资源属性的值。
考虑下面的三元组 (这里 dc 前缀的含义是 Dublin Core)
{dc:Publisher, http://www.w3.org, "World Wide Web Consortium"}
{dc:Title, http://www.w3.org, "W3C Home Page"}
这些三元组能够被图形化地表示为这样
[graph1]
在这个图形中弧线被标记为 predicate。每条弧线从一个代表 subject 的节点出发,终止于一个代表 object 的节点。三元组和图形是同一 RDF 数据模型的两种不同表示。
对于这个模型也有一个 XML 的表示。RDF 要求不同类别的语义信息 (例如,题目,属性和值) 被放置在 XML 中指定的地点。 读取一个 XML 编码的 RDF 程序随后可以确定是否一个特定的元素或属性指示一个主题,一个属性或一个属性的值。
Jena API
Jena 由 HP 公司的 Brian McBride 开发,起源于早些时候 SiRPAC API 的工作。Jena 允许你来解析,创建和查询 RDF 模型。
Jena 定义了很多的接口来访问和处理 RDF statement,如下图所示
[image2]
RDFNode 接口为所有的可以作为一个 RDF 三元组一部分的元素提供了一个公共的基础。Literal 接口表示字面值,例如 “red fish” 或 225,可以被用来作为 {predicate, subject, object} 三元组中的 < object>。Literal 接口提供了将字面值转换为诸如 String,int 和 double 这样的 Java 类型的访问方法。
实现 Property 接口的对象可以作为 {predicate, subject, object} 三元组中的 < predicate>。
Statement 接口表示一个 {predicate, subject, object} 三元组。它也可以被用来作为一个三元组中的 < object>,因为 RDF 允许 statement 嵌套。
实现 Container,Alt,Bag 或 Seq 的对象可以作为三元组中的 < object>。
使用 Jena 解析 RDF
一个 RDF 非常有用的领域是在 Web 页面中嵌入元数据。这个 RDF 能够被编码为嵌入在 XHTML 页面中的 XML。
一个了解 RDF 的搜索引擎能够使用这些元数据来给出比一个仅仅靠关键字匹配的搜索引擎给出的更加关联的结果。一个了解 RDF 的搜索引擎爬虫能够使用 Jena 来解析 RDF,这由 Model 接口里的 read() 方法来完成,就象以下代码显示的那样(为清晰起见,例外处理已被省略)
File f;
FileReader fr;
Model model;
f = new File("C:\test1.html");
fr = new FileReader(f);
model = new ModelMem();
model.read(fr, RDFS.getURI());
在这个例子中,C: est.html 是一个有 RDF 在 元素中的 XHTML 文件。Jena 自动提取 RDF 并忽略 XHTML 的其余部分。解析的结果是一个包含文件中三元组的 RDF 模型。这个模型随后可以被查询。
代码片段中声明之后的前两个语句将 fr 设置为一个与 C: est.html 相关联的 FileReader。model 被设置为一个 ModelMem 类的实例。ModelMem 是一个 Jena 提供的类,实现 Model 接口,使用主内存来存储模型。其它的实现也是可能的;例如,你可以创建一个基于事务处理数据库的实现。
从一个模型中得到所有的 Statements
一旦一个搜索引擎爬虫创建了一个包含一个 Web 页面元数据的 RDF 模型,它需要添加每个三元组到它的索引中,这样以后搜索就可以找到这个页面。这可以由 Model 接口的 listStatements() 方法来完成。listStatement() 返回一个 StmtIterator 来迭代模型中的每个 statement。它可以象这样来使用
Model model;
StmtIterator iter;
Statement stmt;
.
.
.
iter = model.listStatements();
while (iter.hasNext()) {
stmt = iter.next();
// Now use
}
Statement 接口提供了访问 satement 中 predicate,subject 和 object 的方法,如下所示
Property predicate;
Resource subject;
RDFNode obj;
Statement stmt;
.
.
.
subject = stmt.getSubject();
System.out.println("Subject = " + subject.getURI());
predicate = stmt.getPredicate();
System.out.println("Predicate = " +predicate.getLocalName());
obj = stmt.getObject();
System.out.println("Object = " + obj.toString());
添加 Statement 到一个模型
并非所有应用程序都从 XML 或 XHTML 文件中读取 RDF,很多需要创建基于用户输入或其它数据的 RDF Statement。考虑一个用来维护 email 消息,浏览器书签和日历条目的可查询档案库的 RDF 个人信息管理器。当程序接收到一个新的 email 消息时,它能够提取出发送者和主题,为其创建 RDF 三元组。它也允许用户输入关于消息讨论的主题的信息,并创建包含该主题的 RDF 三元组。
下面的代码演示了 Jena 怎样能够用来在一个模型中创建三元组
Model model;
String namespace = "http://www.test.com";
.
.
.
model.createResource("http://www.foo.com/boats#sailboat")
.addProperty(model.createProperty(namespace, "length"), 25)
.addProperty(model.createProperty(namespace, "color"), "teal");
这段代码添加了下面的 statements 到模型中
{x:length, http://www.foo.com/boats#sailboat, 25}
{x:color, http://www.foo.com/boats#sailboat, "teal"}
这里 x 是一个名域前缀,对应于名域的 URI http://www.test.com
查询模型
一旦一个 RDF 模式被创建,我们需要一种方法来查询它,例如,考虑一个包含 RDF 元数据的旅游 FAQ。假设我们想找到所有与非洲旅行有关的问题,换句话说我们希望找到在模型中所有具有形式 {destination, res, Africa} 的 res 的值。下面的代码显示怎样完成这件事。它任意假设属性的目的地是在一个 http://foo.org 的名域中。
Model model;
Resource r;
ResIterator resourceIter;
.
.
.
resourceIter = model.listSubjectsWithProperty(
model.createProperty("http://foo.org/destination"),
"Africa");
while (resourceIter.hasNext()) {
r = resourceIter.next();
System.out.println("Resource " + r.toString() +
" is about travel to Africa");
}
listSubjectsWithProperty(p, v) 为任何 < subject> 查找所有的 {p, < subject>, v} 形式的三元组。它返回一个迭代匹配的三元组对象。
哪里能够得到 Jena
Jena 可以从这里下载 http://www.hpl.hp.co.uk/people/bwm/rdf/jena/download.htm 。下载文件包括一些例子,JavaDoc,源代码和 jar 文件。
致谢
感谢 Brian McBride 为这篇文章的草稿所写的富有帮助的评论和创建了 Jena。
--dlee
有人说一个人有烦恼是因为记性太好。那年开始,我忘记了很多事情,唯一有印象的,就是我喜欢桃花。
|
|
|
[Original]
[Print]
[Top]
|
|
[Original]
[Print]
[Top]
|
使用 Jena 处理 RSS 1.0
作者:Brian McBride
发表时间:2000年9月2日
原文链接: http://www.hpl.hp.co.uk/people/bwm/rdf/jena/rssinjena.htm
译者:dlee
翻译时间:2001年5月26日
RSS 1.0 是最近宣布的一个格式,顺从于 W3C 的 RDF (资源定义框架),用来分发(distributing) 站点摘要 (site summary) 和企业联合 (syndication) 元数据。一个站点摘要文档的例子可以在规范中找到。Jena 是一套实验性的用来处理 RDF 的 Java API。这篇笔记描述了一个应用程序使用 Jena 来将一个站点摘要文档翻译成 HTML。整个程序的源代码作为 RenderToHTML 可以在 Jena 发布的例子包里得到。
这篇文章和例子代码基于 RSS 规范候选发布版本1 (Release Candidate 1 version)。
这个应用程序以创建一个 RDF 模型开始,实际上在内存中是一个 RDF statement 的集合。然后解析站点摘要文档,使用一个 RDF 解析器,并加载 statement 到新创建的模型中。
Model model = new ModelMem();
model.read(" http://www.xml.com/xml/news.rss");
在写出一个样板 HTML 头后,程序列出和处理在输入流中的每个 channel。在 RDF 术语中,channel 是具有一个 rdf:type 属性的 rss:channel 的资源。我们使用 Jena API 来列出具有一个有这个值的 rdf:type 属性的所有的资源。在下面的代码中,假设输出是一个接收 HTML 输出的 PrintWriter。
ResIterator channels = model.listSubjectsWithProperty(RDF.type, RSS.channel);
while (channels.hasNext()) {
renderChannel(channels.next(), out);
}
为了呈现 (render) 一个 channel,程序首先写出它的 title,description 和相关的 image 和 textinput 字段 (如果有的话)。getProperty 方法用来得到 channel 的 title,link 和 description 属性,随后这些可以被呈现为 HTML。
void renderChannel(Resource channel, PrintStream out)
throws RDFException {
String url = null;
String title = null;
String desc = null;
url = channel.getProperty(RSS.link).getString();
title = channel.getProperty(RSS.title).getString();
desc = channel.getProperty(RSS.description).getString();
一个 channel 可以有一个相关联的 image 和 textinput,测试是否存在这些属性和是否需要调用合适的方法来呈现它们是很简单的。
if (channel.hasProperty(RSS.image)) {
renderImage(channel.getProperty(RSS.image) .getResource(), out);
}
if (channel.hasProperty(RSS.textinput)) {
renderImage(channel.getProperty(RSS.textinput) .getResource(), out);
}
为了处理一个 image,同样的调用被用来确定 image 的属性。
String url = null;
String title = null;
// does the image have a link?
if (image.hasProperty(RSS.link)) {
url = image.getProperty(RSS.link).getString();
}
// does the image have a title?
if (image.hasProperty(RSS.title)) {
title = image.getProperty(RSS.title).getString();
} image.getProperty(SSF.title).getString();
然后这个 image 可以被呈现成为 output stream。textinput 以 相似的方法处理。
channel 有一个 items 属性,它的值为一个 RDF sequence。因此使用 getProperty 方法得到这个 sequence 就很简单的了。然后迭代每一个元素以呈现它。
if (channel.hasProperty(RSS.items)) {
Seq items = channel.getProperty(RSS.items).getSeq();
for (int i=1; i<= items.size(); i++) {
renderItem(items.getResource(i), out);
}
}
以相同的模式呈现每一个 items。首先得到需要呈现的 items 的属性,然后写出 HTML。
void renderItem(Resource item, PrintWriter out) {
String url = item.getProperty(RSS.link).getString();
String title = item.getProperty(RSS.title).getString();
String desc = item.getProperty(RSS.description) .getString();
...
}
使用 Jena 来处理 RSS 1.0 流是简单和直接的。
Brian McBride
HP实验室,2000年9月2日
修改于2000年12月2日
--dlee
有人说一个人有烦恼是因为记性太好。那年开始,我忘记了很多事情,唯一有印象的,就是我喜欢桃花。
|
|
|
--
|
|
[Original]
[Print]
[Top]
|
|
|