html容器元素
在本系列的最后一篇文章中 ,我开始研究如何在XML设计中将元素组织成结构。 在本文中,我将继续讨论元素结构,并考虑何时以及如何在相关元素组周围使用容器元素的问题。
XML建模只是数据建模的一个子集。 我将数据建模定义为将现实世界的现象转换为抽象的正式模型以支持计算机应用程序的任何活动 。 参与XML设计的许多人都有计算机编程设计的背景。 此背景涉及熟悉常见数据结构,包括用于标识和引用数据结构实例的工具。 这些问题中的一些在良好的XML设计中几乎是相同的,而另一些则需要一些转变。
包装元素
我从XML设计人员那里听到的一个非常普遍的问题是何时使用容器元素(也称为包装器元素)包装元素组。 在本节中,我演示什么是容器元素。 清单1是一个库的清单文件,它是一组同类元素的示例。
清单1.没有特殊包装的一组元素的示例
<library>
<name>The XML Institute Public Library</name>
<book isbn="0764547607">
<title>The XML Bible, 2nd Edition</title>
</book>
<book isbn="0321150406">
<title>Effective XML</title>
</book>
<book isbn="1861005946">
<title>Beginning XSLT</title>
</book>
</library>
book
元素只是作为name
元素的同级元素出现在系列中。 问题是,插入容器元素是否是更好的设计实践,如清单2所示。
清单2.带有容器的一组同类元素的示例
<library>
<name>The XML Institute Public Library</name>
<books>
<book isbn="0764547607">
<title>The XML Bible, 2nd Edition</title>
</book>
<book isbn="0321150406">
<title>Effective XML</title>
</book>
<book isbn="1861005946">
<title>Beginning XSLT</title>
</book>
</books>
</library>
books
元素用作容器。 出于多种原因,您可能希望使用容器元素。 容器在编程设计中更为常见。 作为示例,清单3是一种与库清单文档相对应的伪代码数据结构。
清单3.基于清单1的编程语言结构的示例
structure library
begin
string name;
list<book> books;
end;
structure book
begin
string isbn;
string title;
end;
该library
结构包括一个参考, name
,以类型的对象string
和参考, books
,到指定类型的对象保持一个列表对象book
。 结构book
非常简单。 编程中对books
参考书的需求经常使程序员开始期望XML设计中需要这种构造。 这不是我经常看到的唯一遗留物。 另一个原因是,许多人都习惯的事实之间的关系, book
的结构和它的isbn
成员是一样的,要其title
成员; 这些人通常最终都将其表示为元素或属性,而没有考虑到在XML设计中,前者最好表示为属性,而后者更好地表示为子元素(有关此内容的更多信息,请参阅本系列的前几篇文章)。
现实世界与代码世界
再看一下清单3 。 实际上,这些编程结构与清单1甚至清单2中的元素结构本质上有很大不同。 结构成员实际上是对其他数据的命名引用。 关键是名称- name
, books
等-并不代表实际的字符串或书籍列表数据项(在OO语言中称为对象 ),而是代表结构的每个实例之间的关系和这些对象(在OO建模中称为关联 )。 在大多数编程语言中,您可以一并处理对象引用和实际引用的对象,而无需考虑两者之间的区别(尽管先进的技术和对大多数语言的坚定要求要求程序员彻底理解这一区别)。 清单4是对XML的非常直观的转换,其中考虑了这一区别。
清单4.从清单3的结构到XML的文字转换
<library>
<name>
<string>The XML Institute Public Library</string>
</name>
<books>
<list member-type="book">
<member index="0">
<book isbn="0764547607">
<title>The XML Bible, 2nd Edition</title>
</book>
</member>
<member index="1">
<book isbn="0321150406">
<title>Effective XML</title>
</book>
</member>
<member index="2">
<book isbn="1861005946">
<title>Beginning XSLT</title>
</book>
</member>
</list>
</books>
</library>
在设计XML时,您可能比用这个字面值更了解,因为您知道您是根据现实生活对实际的图书馆目录概念进行建模,而不是用计算机代码来表示。 这种了解是实现容器元素何时合适的关键(对于XML设计的许多其他方面也很关键)。
在XML设计中,请避免与您正在建模的任何现实现象都不对应的构造。
您可以立即将此测试应用到清单2中 ,因为元素books
并没有真正对应于在建模中的现实现象中有用的任何东西。 该库本身是一个隐式的书籍集合,因此并不需要真正的显式books
容器。 再举一个例子,假设文章被整理成几本书,并集体捐赠。 在这种情况下,添加一个容器元素确实很有意义,如清单5所示,因为它对应于现实世界的概念。
清单5.有意义的容器元素的示例
<library>
<name>The XML Institute Public Library</name>
<endowment>
<donor>IBM</donor>
<book isbn="0764547607">
<title>The XML Bible, 2nd Edition</title>
</book>
<book isbn="0321150406">
<title>Effective XML</title>
</book>
</endowment>
<endowment>
<donor>W3C</donor>
<book isbn="1861005946">
<title>Beginning XSLT</title>
</book>
</endowment>
</library>
注意,我更喜欢使用更有意义的名称“捐赠”,而不是仅仅使用“书籍”来表示图书馆中书籍集合的元素结构。
但是工具呢?
一些开发人员总是使用容器元素,因为他们发现他们的工具更容易处理此类XML。 选择工具几乎总是一个问题,而不是向XML设计中引入麻烦的一个很好的理由。 正如作者Eric van der Vlist在一个有助于启发本文的电子邮件主题中指出的那样:
我倾向于认为工具对文档设计的影响应该是有限的(当然不会到根本无法处理文档的地步),好的设计并不一定会引入所有限制。工具。
幸运的是,XML的示例工具在支持容器元素方面没有愚蠢的限制。 清单6是XSLT的摘要,它说明了如清单1所示处理XML的简便性。
清单6. XSLT框架,用于处理没有容器的元素组
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
>
<xsl:template match="library">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="name">
<xsl:apply-templates/> <!-- only text node children -->
</xsl:template>
<xsl:template match="book">
<!-- Add code to process @isbn attribute here -->
<xsl:apply-templates/> <!-- Takes care of title child -->
</xsl:template>
</xsl:transform>
此清单不包含容器元素的事实并不限制XSLT的功能或表达能力,尤其是如果您使用的拉法主要集中在相对独立的模板上。 例如,如果您希望按它们在文档中出现的顺序处理所有的library
子项,然后仅处理book
子项,则可以使用模板模式轻松地对此进行管理,如清单7所示。
清单7.示例XSLT框架,可以在没有容器的情况下更加灵活地处理元素组
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
>
<xsl:template match="library">
<!-- process all children in document order -->
<xsl:apply-templates/>
<!-- process only book element children -->
<xsl:apply-templates select="book" mode="books"/>
</xsl:template>
<xsl:template match="name">
<xsl:apply-templates/> <!-- only text node children -->
</xsl:template>
<xsl:template match="book">
<!-- When this template is invoked, there may be other
types of elements in this (the default) mode -->
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="book" mode="books">
<!-- Only book elements are processed in this mode,
allowing more specialized processing -->
<xsl:apply-templates/>
</xsl:template>
</xsl:transform>
既然您正在处理XML文档的实际处理,那么引入特定于程序的抽象(例如books
(在本示例中表现为XSLT模式)就变得十分合理。 将这些处理工件保留在源数据之外是XML设计中最重要的考虑因素之一。 数十年的计算机历史表明,代码来了而代码就走了,但是数据实际上永远存在。
结语
在本文中,我重点介绍了用于均质元素组的容器的选择。 即使容器中考虑的元素组不同,基本问题和原理也相似。 XHTML中的head
元素是异构容器的一个示例,它包装了从title
到meta
元素。 值得注意的是,根据我的经验,我发现为异类元素的容器找到真实世界的类似物并不少见。
正如我前面提到的那样,可以以与编程设计几乎相同的方式来处理其中的一些XML设计问题,而某些问题则需要一些角度上的转变。 即使XML设计相对于常规编程或数据库设计而言对您来说不便绕道而行,它引入的新鲜观点也将帮助您成为更好的总体数据设计人员。 一个可能是新原理的原则是数据建模和过程建模之间的完全分离。 我发现将这一原则牢记在心(根据我对XML的经验)使我成为了一个更好的代码设计者。 即使在我的代码设计最终合并了数据和处理模型的地方,从分别考虑数据和代码的原则出发,对组合的模型进行了一些微调。
翻译自: https://www.ibm.com/developerworks/xml/library/x-contain/index.html
html容器元素