文档格式的排错:我妈妈_的清单中有数十条菜谱,甚至数百条。如果产生一个致命错误,排错将非常困难 - 你将一行一行地寻找丢失的标记符。如果使用几层嵌套,发现错误将很困难。
但是可以找到很好的帮助。分析器 - xml代码和报告格式错误的应用程序可以在网上免费得到。其中最好的是lark,它的作者是由tim bray - xml规范的技术编辑和极力鼓吹者,地球上最聪明的人之一。
我用lark分析下面的代码。注意"chocolate chips"和它的关闭标记符出现在</ingredients> 标记符中的位置有错误:
<?xml version="1.0"?>
<list>
<recipe>
<author>carol schmidt</author>
<recipe_name>chocolate chip bars</recipe_name>
<meal>dinner
<course>dessert</course>
</meal>
<ingredients>
<item>2/3 c butter</item>
<item>2 c brown sugar</item>
<item>1 tsp vanilla</item>
<item>1 3/4 c unsifted all-purpose flour</item>
<item>1 1/2 tsp baking powder</item>
<item>1/2 tsp salt</item>
<item>3 eggs</item>
<item>1/2 c chopped nuts</item>
<item>
</ingredients>2 cups (12-oz pkg.) semi-sweet choc.
chips</item>
<directions>
preheat overn to 350 degrees. melt butter;
combine with brown sugar and vanilla in large mixing bowl.
set aside to cool. combine flour, baking powder, and salt; set aside.
add eggs to cooled sugar mixture; beat well. stir in reserved dry
ingredients, nuts, and chips.
spread in greased 13-by-9-inch pan. bake for 25 to 30 minutes
until golden brown; cool. cut into squares.
</directions>
</recipe>
</list>
下面是分析器返回的结果:
error report
line 17, column 22: encountered </ingredients> expected </item>
... assumed </item>
line 18, column 36: encountered </item> with no start-tag.
有了这种信息,找到错误将不会成为问题。那么xml文件的有效性是指什么呢?
实现有效性最终我们将在组织良好的xml文档中加入信息。实际上,我们有很多事要做 - 仍然有危机潜伏 - 虽然xml文件组织良好,
但还可能丢失关键信息。看看下面的例子:
<recipe>
<author>carol schmidt</author>
<recipe_name>chocolate chip bars</recipe_name>
<meal>dinner <course>dessert</course> </meal>
<ingredients> </ingredients>
<directions>melt butter; combine with, etc. ... </directions>
</recipe>
这份菜谱中没有包含ingredient,而且因为它组织良好,所以lark分析器也不会发现问题。管理过哪怕是最和善的数据库的人都知道我们人类常犯的错误:如果有机会,我们会丢掉关键信息并加入无用的废话。这就是为什么xml的发明者引入dtd - 文档类型定义(document type definition)。dtd提供了一种保证xml或多或少是你所想的方法。
让我们看看用在菜谱上的一个dtd。
<!doctype list [
<!element recipe (recipe_name, author, meal, ingredients, directions)>
<!element ingredients (item+)>
<!element meal (#pcdata, course?)>
<!element item (#pcdata, sub_item*)>
<!element recipe_name (#pcdata)>
<!element author (#pcdata)>
<!element course (#pcdata)>
<!element item (#pcdata)>
<!element subitem (#pcdata)>
<!element directions (#pcdata)>
]>
这些代码起初看起来不够友好,但当把它分解时却能看出其中的意义。让我们详细解释之:
<!doctype list [
这行是说,包含在方括号中的是具有根元素<list>的某个文档的dtd。如我们以前提到的,根元素包含所有其它元素。
<!element recipe (recipe_name, meal, ingredients, directions)>
这行定义了<recipe>标记符。圆括号是说其中的四种标记符必须按照顺序出现在<recipe>标记符中。
<!element meal (#pcdata, course?)>
这行需要详细的解释。我定义了以下的结构:
<meal>here the meal name is mandatory
<course>one course name may appear, but it is not
mandatory</course>
</meal>
我这样做是因为,按照我的想法,午餐不一定特定某道菜,但是晚餐可能要指出开胃食品、主菜和餐后甜点。通过指定#pcdata - 表示经过分析的字符数据(即非二进制数据)来实现这个功能。这里,#pcdata是文本 - 例如,“dinner”。
"course"后面的问号表示0或1对<course>标记符将出现在<meal>标记符内。
现在让我们看看下一行:
<!element ingredients (item+)>
这里的加号表示至少有一对<item>标记符应出现在<ingredients>标记符内。
我们感兴趣的最后一行是:
<!element item (#pcdata, sub_item*)>
我把sub_item*作为一项安全措施。除了要求每个item的文本之外,我希望计算每个item的内容的数量。星号是说在<item>标记符中可以有子条目的数目。我不需要chocolate chip bars菜谱的任何子条目,但是当它的组成成分很复杂时就用得着。
现在让我们把这些放在一起看看我们能得到什么。
dtd的完整例子
下面是一个完整的例子。我把另一个菜谱加入文件内,并为dtd做了注释。可以注意到我在第二个菜谱中用到子条目。
<?xml version="1.0"?>
<!--this starts the dtd. the first four lines address document structure-->
<!doctype list ][
<!element recipe (recipe_name, author, meal, ingredients,directions)>
<!element ingredients (item+)>
<!element meal (#pcdata, course?)>
<!element item (#pcdata, sub_item*)>
<!--these are the remaining elements of the recipe tag -->
<!element recipe_name (#pcdata)>
<!element author (#pcdata)>
<!element directions (#pcdata)>
<!--the remaining element of the meal tag -->
<!element course (#pcdata)>
<!--the remaining element of the item tag -->
<!element sub_item (#pcdata)>
]>
<?xml version="1.0"?>
<list>
<recipe>
<author>carol schmidt</author>
<recipe_name>chocolate chip bars</recipe_name>
<meal>dinner
<course>dessert</course>
</meal>
<ingredients>
<item>2/3 c butter</item>
<item>2 c brown sugar</item>
<item>1 tsp vanilla</item>
<item>1 3/4 c unsifted all-purpose flour</item>
<item>1 1/2 tsp baking powder</item>
<item>1/2 tsp salt</item>
<item>3 eggs</item>
<item>1/2 c chopped nuts</item>
<item>2 cups (12-oz pkg.) semi-sweetchoc. chips</item>
</ingredients>
<directions>
preheat oven to 350 degrees. melt butter;
combinewith brown sugar and vanilla in large mixing bowl.
set aside to cool. combine flour, baking powder, andsalt;
set aside.add eggs to cooled sugar mixture; beat well.
stir in reserved dry ingredients, nuts, and chips.
spread in greased 13-by-9-inch pan.
bake for 25 to 30minutes until golden brown; cool.
cut into squares.
</directions>
</recipe>
<recipe>
<recipe_name>pasta with tomato sauce</recipe_name>
<meal>dinner
<course>entree</course>
</meal>
<ingredients>
<item>1 lb spaghetti</item>
<item>1 16-oz can diced tomatoes</item>
<item>4 cloves garlic</item>
<item>1 diced onion</item>
<item>italian seasoning
<sub_item>oregano</sub_item>
<sub_item>basil</sub_item>
<sub_item>crushed red pepper</sub_item>
</item>
</ingredients>
<directions>
boil pasta. sauté garlic and onion.
add tomatoes.serve hot.
</directions>
</recipe>
</list>
既然有dtd,文档将被检查看是否符合dtd做出的限制。换句话说,我们要保证文档的有效性。
为了达到这个目的,我们需要另一个工具:有效性分析器。微软的msxml,一个基于java的程序,使用容易又工作得很好。上面的文档经过这个程序的检查后没有发现错误。但是如果我检查一个ingredient标记符中没有包含条目的菜谱,将会返回以下信息:
ingredients is not complete. expected elements [item].
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器