xml文件详解

来源:互联网 发布:张悦然 知乎 编辑:程序博客网 时间:2024/06/05 05:05

 到目前为止,我撰写了很多关于 XML 及相关内容的文章和书籍,当回头重新审视这些文字的时候,结果却令我很吃惊。虽然我是一位程序员,喜欢深入到比特和字节(上大学的时候非常喜欢汇编语言),喜欢那种绝对控制的感觉,但总的来看,我的文章、技巧和著作关于 XML 本身讨论得越来越少,关于操作 XML 的 API、包装这些 API 的 API 以及根本不触及 XML 的其他 API 讨论得越来越多。

因此结果就是一个共性的问题:是否还记得如何实际编写好的 XML 文档?还知道如何区分 XML 好坏的标准么?本文回顾了几篇 XML 101 技巧系列的文章,希望我们在拥有各种工具的同时不会遗忘那些基本的原理。

第一步:正确使用不同的 XML 成分

最突出的显著问题之一是 XML 作者(从宽泛的意义上讲)将各种各样的内容都填塞到元素中。属性、处理指令 — 变成了过去时。

元素

元素在 XML 中最容易使用,很大程度上是因为 XML 作者倾向于完全 依靠元素。当然,这是错误 的,而且有很严重的副作用。XML 中的元素最适合表示具有某种层次结构或者可能 具有某种层次结构的数据(当然也有例外,不过这里讨论的是最佳用法)。首先举一个反例,人名(不含姓和中间名等)永远不可能有层次结构,它就是一个单词,如此而已。但是如果选择使用 name 元素,可能 也不错:至少能分解成名和姓,可能还有中间名、头衔和其他成分。因此下面这样使用元素实际上是不正确的:

<firstName>Bob</firstName>
 


应该用:

<name firstName="Bob"
 lastName="Zemeckis"
 title="Mr." />
 


如果还不明白为何不在 name 元素中嵌套 firstName、lastName 以及 title 元素,请仔细阅读 上一段。下一节介绍 属性 时还将进一步讨论。

一般而言,如果一个元素不可能在文档的同一个地方出现多次(比如可能有家庭和办公两个不同类型的 address 元素,图书可能存在两个 author 元素),则应尽量使用属性。并不是说每次使用元素时都必须 出现两次,仅仅是可以 出现两次。

元素最适合文本数据这种说法也不正确,很多例子中元素只有属性而没有文本内容(建议阅读讨论属性的 下一节)。最重要的是要记住 XML 不仅仅 有元素,还有其他结构。

属性

尽管看起来像是废话,但无论如何只能对单值数据使用 XML 属性。比方说,如果使用关于人的元素,那些关于这个人的单值信息就是潜在的属性。社会保障号码、ID,可能还有出生日期 — 都是合适的候选属性。

当然和其他规则相比,属性规则有更多的例外。实际上,我认为属性的应用和应该达到的程度相比少得多。开发人员往往喜欢元素比较清晰的外观:

<person>
 <ssn>489098723</ssn>
</person>
 


但是这样做毫无意义 — 社会保障号码绝对是单值数据。更糟的是,这样把数字当成元素会影响性能。像这种情况下访问元素的子元素时,必须首先取得元素节点然后遍历所有的子元素节点。社会保障号码可能是第一个节点,但也可能是最后一个节点,不能确定。得到那个 节点的子元素后再访问其值,该例中包括一个文本节点。中间要经过多个步骤:

获得父节点(person 元素)。
访问父节点的子节点。
迭代寻找需要的子节点(ssn 元素)。
可能需要规范化这个新元素的文本节点以简化后续操作。
得到元素的子节点。
取得文本子节点的值。
使用属性的话就简单多了:

访问父节点(person 元素)。
访问属性。
迭代寻找需要的属性(ssn)。
取得属性值。
这种方法避免了规范化(属性只能有单一的文本值),也不需要处理子元素。我发现访问元素的属性几乎总比访问特定的子元素快。因此性能上的优势很明显,特别是对于成千上万次迭代的情况。

我的观点是,尽管看起来不太好看,XML 应这样使用:

     <person ssn="489098723"
             firstName="Bobby"
             lastName="McKenza"
     >
       <occupation>
         <occupation-type status="part-time"
                          job="author" />
         <occupation-type status="part-time"
                          job="programmer" />
       </occupation>
       <address type="home"
                street="112 E. Harney Way"
                city="New York"
                state="NY"
                zip="10012" />
       <!-- etc... -->
     </person>
 


对大多数人来说可能有点奇怪,因为基本上所有信息都用属性表示。但是我相信这种方法更好,访问 10,000 或更多次时能够可观地提高效率(访问次数多可以将细微的性能改进叠加起来)。

处理指令

通常不使用处理指令或者 PI。但是,令人苦恼的是现在很多 XML 处理 API 要求把特殊代码或指令放在注释中、或者使用特殊的名称空间以及各种专用元素,甚至使用包含指令的元素。如果 XML 需要为处理 API 或者工具提供信息,这些信息就是处理指令,XML 有专门的机制。

以前肯定遇到过,特别是在 XSL 中:

<?xml version="1.0"?>
<?xml-stylesheet href="classic.xsl" type="text/html"?>
<?xml-stylesheet href="alternate.xsl" type="text/xml" alternate="yes"?>
<article>
 <!-- etc ... -->
</article>
 


这里 PI 告诉 XSLT 处理程序应用于 XML 文档的样式表在哪里。不用考虑那些忽略该机制的 API(尽管首先想到的就是 JAXB),应该充分利用该机制,无论如何要比下面这种方法强:

<?xml version="1.0"?>

<!-- xml-stylesheet url="classic.xsl" document-type="text/html" -->
<!-- xml-stylesheet url="alternate.xsl" document-type="text/xml" -->
<article>
 <!-- etc ... -->
</article>
 


我经常看到这样的代码。注释是没有意义的,使用注释并将其中的信息作为指令处理的 API 是危险的。Javadoc 和文档生成 API 使用注释,但至少作为文档而不是具有实际意义的指令使用。显然,如果选择的 API 要求这种标记,您可能继续使用,但应该认识到这并非按照 XML 本来的方式使用 XML。我相信 XML 规范的作者在这个问题上说得很明确了。
 

 

结束语

 
 
也许我早应该讨论这些问题,但我并不是 XML 纯粹论者。事实上我认为 XML 的很多东西愚蠢无聊、本末倒置或者是完全错误的。但是我的确 认为,既然选择使用 XML,一些基本的概念对于正确使用是必须的,否则何必选择 XML 呢?如果多值数据或者长数据不用元素,如果根本不使用属性,如果滥用或者不用处理指令,某个时候就会发现最好离开 XML 去编写自己的私有语言或解析器来处理您的数据。否则就得忍受 XML 的枷锁 — 冗长、奇形怪状的文档、编码问题等等 — 而没有任何好处 — 专用的高速解析器。

因此不要为了正确地使用 XML 或者取悦语义主宰者而考虑这些建议。对于您的编程生涯来说这些都不是恰当的理由。如果将其看作更有效地利用 XML、提高软件性能的办法,就是合情合理的了。继续前进吧,打破那些规则 —— 但必须有充分的理由!

原创粉丝点击