ITPub博客

首页 > 应用开发 > IT综合 > 使用 XML Schema 定义元素的基本知识(转)

使用 XML Schema 定义元素的基本知识(转)

原创 IT综合 作者:amyz 时间:2007-08-12 15:31:58 0 删除 编辑
使用 XML Schema 定义元素的基本知识(转)[@more@]

  新的 XML Schema 系统即将成为 W3C 推荐标准,目的是为了克服 DTD 的局限性(请参阅侧栏, DTD 的局限性 ),为 XML 文档提供丰富的语法结构。本文展示了模式的灵活性,说明如何使用 XML Schema 系统来定义最基本的 XML 文档构造块——元素。

  XML Schema 比 DTD 更强大。为了说明 XML Schema 机制的强大功能,下面三个程序清单简要比较了表示元素的不同方式。 清单 1给出了一个 XML 文档片段, 清单 2用 DTD 语法声明了这两个元素, 清单 3则是相应的 XML Schema 语法形式。要注意, 清单 3中所用的是相同的 XML 语法。通过模式,验证解析器可以检查元素 InvoiceNo 是否是正整数,元素 ProductID 的首字符是否为 A 到 Z 之间的字母,后面为六个阿拉伯数字。相反,引用 DTD 的验证解析器只能检查这些元素是否用字符串表示。

  清单 1:XML 文档片段

  123456789J123456

  清单 2:描述清单 1 中元素的 DTD 片段

  

  清单 3:描述清单 1 中元素的 XML Schema

  

  在 XML Schema 中使用名称空间

  在这个协作的世界中,一个人可能处理来自多个其他团体的文档,而不同的团体可能希望以不同的方式表示他们的数据元素。此外,他们还可能在一个文档中引用不同团体创建的同名元素。如何区分相同名字的不同定义呢?XML Schema 使用名称空间区分这些定义。

  附:

  DTD 的局限性

  (尽管作为描述结构化信息的一种机制,DTD 成功地为 SGML 和 HTML 开发人员服务了 20 年,但与 XML Schema 相比,它存在着严重的局限性。

  DTD 要求元素由以下三种成分组成:

  • 文本字符串
  • 文本字符串与其他子元素的混合
  • 一组子元素

  DTD 不使用 XML 语法,对类型和名称空间仅提供有限的支持。)

  一个给定的 XML Schema 定义了一组新名字,如元素名、类型名、属性名、属性组名,这些名字的定义和声明都写在模式中。 清单 3定义的名字包括 InvoiceNo 、 ProductID 和 ProductCode 。

  我们说模式中定义的名字属于它的 目标名称空间。名称空间本身有一个固定但没有限制的名字,必须符合 URL 语法。比如,对于 清单 3中模式片段,您可以把名称空间的名字设为: http://www.SampleStore.com/Account 。

  名称空间的名字语法容易让人混淆,尽管以 http:// 开始,那个 URL 并不指向一个包含模式定义的文件。事实上,这个 URL http://www.SampleStore.com/Account 根本没有指向任何文件,只是一个分配的名字。

  模式中的定义和声明可能引用属于其他名称空间的名字。在本文中,我们称这些名称空间为 源名称空间。每个模式都有一个目标名称空间,但可能有多个源名称空间。名称空间的名字可能相当长,但在 XML 文档中通过 xmlns 声明可使用简写形式。为了说明这些概念,我们可以向前述 清单 4中的示例模式中添加更多的内容。

  清单 4:目标名称空间和源名称空间

  <!--XML Schema fragment in file schema1.xsd-->

  在 清单 4的 XML Schema 中, targetNamespace 的名字是 http://www.SampleStore.com/Account ,其中包含的名字有 InvoiceNo 、 ProductID 和 ProductCode 。 schema 、 element 、 simpleType 、 pattern 、 string 和 positive-integer 这些名字属于源名称空间 http://www.w3.org/1999/XMLSchema ,通过 xmlns 声明缩写为 xsd 。别名 xsd 没有任何特殊的地方,我们可以选择任何其他的名字。在本文后面的部分为了方便和简化起见,我们使用 xsd 代表名称空间 http://www.w3.org/1999/XMLSchema ,在一些代码片段中省略了限定符 xsd 。在这个例子中, targetNamespace 偶尔也作为一个源名称空间,因为要使用名字 ProductCode 定义其他的名字。

  图 1:清单 4 中的名称空间

  清单 4中的模式片段不需要指定源模式文件的位置。对于整个“模式的模式”, http://www.w3.org/1999/XMLSchema ,不需要指定位置,因为它的位置是人所共知的。对于源名称空间 http://www.SampleStore.com/Account ,也不需要指定位置,因为它恰好是该文件中定义的目标名称空间。为了更好地理解如何指定模式的位置和使用默认名称空间,看一看 清单 5中扩展的例子。

  清单 5:多个源名称空间,导入一个名称空间

  <!--XML Schema fragment in file schema1.xsd-->

  清单 5中多了一个名称空间引用: http://www.PartnerStore.com/PartsCatalog 。这个名称空间不同于 targetNamespace 和标准名称空间。因此必须使用 import 声明元素引入,该元素的 schemaLocation 属性指明包含模式的文件位置。默认的名称空间是 http://www.w3.org/1999/XMLSchema ,它的 xmlns 声明没有名字。每个非限定的名字如 schema 和 element ,都属于默认名称空间 http://www.w3.org/1999/XMLSchema 。如果模式从一个名称空间中引用了多个名字,将其指定为默认名字空间更方便。

  一个 XML 实例文档可能引用多个名称空间的元素名,这些名称空间定义在不同模式中。为了引用和简化名称空间的名字,同样要使用 xmlns 声明。我们使用 XML Schema 实例名称空间的 schemaLocation 属性指定文件的位置。要注意,该属性不同于上一个例子中 xsd 名称空间的同名属性 schemaLocation 。

  清单 6:使用来自多个模式的多个名称空间的名字

  123456789

  图 2:清单 5 和清单 6 的名称空间

 

  定义元素

  定义元素就是定义元素的名字和内容模型。在 XML Schema 中,元素的内容模型由其类型定义,因此 XML 文档中实例元素的值必须符合模式中定义的类型。

  类型包括简单类型和复杂类型。简单类型的值不能包含元素或属性。复杂类型可以产生在其他元素中嵌套元素的效果,或者为元素增加属性。(到目前为止本文中的例子都是用户定义的简单类型,比如 ProductCode )。XML Schema 规范也包括预定义的简单类型(请参阅侧栏 简单类型)。 派生的简单类型约束了基类型的值。比如,派生简单类型 ProductCode 的值是基类型 string 值的子集。

  简单的、非嵌套的元素是简单类型

  不含属性或其他元素的元素可以定义为简单类型,无论是预定义的简单类型还是用户定义的简单类型,如 string 、 integer 、 decimal 、 time 、 ProductCode 等等。

  清单 7:一些元素的简单类型

  

  带有属性的元素必须是复杂类型

  现在,试着向 清单 7中的简单元素 price 增加属性 currency 。您不能这样做,因为简单类型的元素不能有属性。如果希望增加属性,您必须把 price 元素定义成复杂类型。在 清单 8的例子中,我们定义了一个 匿名类型,没有明确地命名这个复杂类型。换句话说,没有定义复杂类型 complexType 的 name 属性。

  清单 8:一个复杂元素类型

  <!-- In XML instance document, we can write: 45.50 -->

  嵌入其他元素的元素必须是复杂类型

  在 XML 文档中,一个元素可能嵌入其他的元素。这种要求可以在 DTD 中直接表示。但 XML Schema 定义一个元素,这个元素有一个类型,而这个类型可以包含其他元素和属性的声明。 表 1给出了一个简单的例子。

  表 1:DTD 和 XML Schema 中复杂数据类型的比较

  XML 文档

  Cool XML<Title><Author>Cool Guy</Author></Book></CODE></P> <P>  DTD</P> <P>  <CODE><Book><Title>Cool XML<Title><Author>Cool Guy</Author></Book></CODE></P> <P>  XML Schema</P> <P>  <CODE><Book><Title>Cool XML<Title><Author>Cool Guy</Author></Book><!ELEMENT Book (Title, Author)><!ELEMENT Title (#PCDATA)><!ELEMENT Author (#PCDATA)><element name='Book' type='BookType'/><complexType name='BookType'><element name='Title' type='string'/><element name='Author' type='string'/></complexType></CODE></P> <P>  尽管 表 1中的 XML 代码同时满足 DTD 与 XML Schema 片段,但两者之间有一个很大的区别。在 DTD 中所有的元素都是全局性的,而表中的 XML Schema 允许把 Title 和 Author 定义成局部的——只出现在元素 Book 中。为了在 XML Schema 中实现与 DTD 声明完全相同的效果,元素 Title 和 Author 必须是全局范围的,如 清单 9中所示。元素 element 的 ref 属性使您能够引用前面声明的元素。</P> <P>  清单 9:用全局简单类型定义的复杂类型</P> <P>  <CODE><element name='Title' type='string'/><element name='Author' type='string'/><element name='Book' type='BookType'/><complexType name='BookType'><element ref='Title'/><element ref='Author'/></complexType></CODE></P> <P>  在 表 1和 清单 9所示的例子中, BookType 是全局性的,可用于声明其他元素。相反, 清单 10将该类型局部地定义到元素 Book 中,而且定义成匿名元素。要注意, 表 1中的 XML 文档片段与表 1、 清单 9和 清单 10中三个模式片段都匹配。</P><P></P> <P>  清单 10:隐藏 BookType 作为本地类型</P> <P>  <CODE><element name='Title' type='string'/><element name='Author' type='string'/><element name='Book'><complexType><element ref='Title'/><element ref='Author'/></complexType></element></CODE></P> <P>  表示元素的复杂约束</P> <P>  对于表示元素内容模型的约束,XML Schema 比 DTD 提供了更大的灵活性。在最简单的层次上,像在 DTD 中那样,您可以把属性和元素声明关联起来,指明能够出现的给定元素集合序列:只能出现 1 次(1)、出现 0 次或多次(*)或者出现 1 次或多次(+)。您还可以表示 XML Schema 中的其他约束,比方说使用 element 元素的 minOccurs 和 maxOccurs 属性,以及 choice 、 group 和 all 元素。</P> <P>  清单 11:表示元素类型的约束</P> <P>  <CODE><element name='Title' type='string'/><element name='Author' type='string'/><element name='Book'><complexType><element ref='Title' minOccurs='0'/><element ref='Author' maxOccurs='2'/></complexType></element></CODE></P> <P>  在 清单 11中, Book 中 Title 的出现是可选的(类似 DTD 的 '?')。但是, 清单 11也说明 Book 元素中至少要有一个但不能超过两个作者。 element 的 minOccurs 和 maxOccurs 属性的默认值是 1。元素 choice 只允许它的一个子女出现在实例中。另外一个元素 all ,表示这样的约束:组中的所有子元素可以同时出现一次,或者都不出现,它们可以按任意的顺序出现。 清单 12表示 Title 和 Author 两者必须同时出现(顺序任意)在 Book 中,或者都不出现。这种约束很难在 DTD 中表示。</P> <P>  清单 12:指出必须为元素定义所有的类型</P> <P>  <CODE><xsd:element name='Title' type='string'/><xsd:element name='Author' type='string'/><xsd:element name='Book'><xsd:complexType><xsd:all><xsd:element ref='Tile'/><xsd:element ref='Author'/></xsd:all></xsd:complexType></xsd:element></CODE></P><P></P> <P>  更上层楼</P> <P>  我们已经讨论了在 XML Schema 中定义元素所需的最基本的概念,通过一些简单的例子使您领略到它的强大功能。还有一些更强大的机制:</P> <UL> <LI>XML Schema 对类型继承提供了广泛的支持,允许重用以前定义的结构。使用所谓的 facets,您可以派生新的类型,表示其他某个类型值的更小子集,比如通过枚举、范围或模式匹配来定义子集。在本文的例子中, ProductCode 类型就是使用模式面( pattern facet)定义的。子类型也可以向基类型增加更多的元素和属性声明。 <LI>有几种机制控制能否定义子类型,或者能否在具体的文档中替换为子类型。比如,有可能表示 InvoiceType ( Invoice 编号的类型)不允许子类型化,任何人都不能定义新版本的 InvoiceType 。通过规定在特定的上下文中不能用 ProductCode 类型的子类型替换,也能表达这种约束。 <LI>除了子类型外,还可以定义等价的类型,这样,一个类型的值可以用另一个类型代替。 <LI>通过声明抽象的元素或者类型,XML Schema 提供了一种强制替换机制。 <LI>为了方便起见,可以定义并命名属性组和元素组,从而能够在后面引用这些组达到重用的目的。 <LI>XML Schema 提供了三个元素—— appInfo 、 documentation 和 annotation ——为模式作注解,以方便读者( documentation )和应用程序( appInfo )。 <LI>基于子元素的某些属性可以表示惟一性约束。 </LI></UL> <P>  可以通过 W3C 站点(请参阅 参考资料)的文档进一步研究 XML Schema,或者访问 dW XML 专区了解更多的内容。目前,XML Schema 规范已经被批准,并成为候选推荐标准(Candidate Recommendation),毫无疑问您将越来越多地用到它。</P> <P></P><BR> </div> <p style="clear:both;"></p> <p class="translate"> 来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10752019/viewspace-950386/ ,如需转载,请注明出处,否则将追究法律责任。 </p> <!-- --> </div> </div> <div class="preview-footer clearfix"> <!--已点赞、收藏--> <div class="icon-praise" id="praise" onclick="blogObj.praise($(this),'/praise/')"><span class="text"></span><span class="num">0</span></div> <div class="icon-collect" id="collect" onclick="blogObj.praise($(this),'/favour/')"><span class="text"></span><span class="num">0</span></div> <div class="share-group fr"> <div class="bdsharebuttonbox bdshare-button-style0-16" data-bd-bind="1522216707615"> <span class="fl">分享到:</span> <a href="javascript:;" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博"></a> <a href="javascript:;" class="bds_sqq" data-cmd="sqq" title="分享到QQ好友"></a> <a href="javascript:;" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间"></a> <a href="javascript:;" class="bds_weixin" data-cmd="weixin" title="分享到微信"></a> </div> <script> window._bd_share_config = { "common": { "bdSnsKey": {}, "bdText": "", "bdDesc": "", "bdMini": "", "bdMiniList": false, "bdPic": "", "bdStyle": "0", "bdSize": "32" }, "share": {"bdSize": 16} }; with (document) 0[(getElementsByTagName('head')[0] || body).appendChild(createElement('script')).src = '/static/api/js/share.js?v=89860593.js?cdnversion=' + ~(-new Date() / 36e5)]; if ($(window).width() < 1320) { if ($(window).width() < 1200) { $(".sideslip").css({ "left": "20px", "margin-left": 0 }) } else { $(".sideslip").css({ "margin-left": "-590px" }) } }</script> </div> </div> <div class="article-context"> <div class="fl"> <span class="color77">上一篇:</span> <a href="https://blog.itpub.net/10752019/viewspace-950385/">构建基于Web/XML的信息集成研究(转)</a> </div> <div class="fr"> <span class="color77">下一篇:</span> <a href="https://blog.itpub.net/10752019/viewspace-950387/">观看外部引用dtd的note.xml(转)</a> </div> </div> <input type="hidden" id="blogId" name="blogId" value="950386"> <!--评论开始--> <div class="blog-comment"> <div class="new-comment"> <input type="hidden" id="hid" name="hid" value="950386"> <input type="hidden" name="_token" value="kUyp4c7RJkmMhOlARRbAhDI1hGdbxa4k6rXMRV01"> <a class="avatar" href="javascript:;"> <img src="/images/user_pic_default.png"></a> <!--用户未登录--> <div class="sign-container"> <span>请登录后发表评论</span> <a class="btn btn-sign"> <a class="layui-btn ml30" onclick="blog.login(event)">登录</a> </a> </div> <!--用户已登录--> <textarea placeholder="请写下你的评论…" onfocus="blogObj.textareaFocus($(this),200)" maxlength=200></textarea> </div> <div class="comment-list"> <div class="top-title"><span class="all-comment">全部评论</span> <span class="colorbb ml20"></span> </div> <div class="comment-items" id="comment_items"> <script type="text/template" id='blog_template'> <%for(var i=0;i <items.length;i++){%> <div class="comment-item"> <div class="author"> <a target="_blank" href="/<%=items[i].uid%>" class="avatar"> <img src="<%=items[i].headimg%>" alt=""> </a> <div class="info"> <div class="name"><a target="_blank" href="/<%=items[i].uid%>"><%=items[i].username%></a> <span class="fr reply-btn" onclick="blogObj.newComment($(this),'<%=items[i].username%>',<%=items[i].id%>)">回复</span> </div> <div class="time colorbb"><%=items[i].createtime%></div> </div> </div> <p class="comment-wrap"><%=items[i].content%></p> <%if(items[i].items.items.length) { %> <div class="sub-comment-list"> <%for(var j=0;j <items [i].items.items.length;j++){%> <div class="sub-comment"> <div class="color77 time-reply"> <span class="time"><%=items[i].items.items[j].createtime%></span> <span class="reply-btn fr" onclick="blogObj.newComment($(this),'<%=items[i].items.items[j].username%>',<%=items[i].items.items[j].id%>)">回复</span> </div> <p><a href="/<%=items[i].uid%>"><%=items[i].items.items[j].username%></a>   回复   <a href="/<%=items[i].touid%>"><%=items[i].items.items[j].tousername%></a>: <span class="content"><%=items[i].items.items[j].content%></span></p> </div> <%}%> <%if(items[i].items.total > 5) { %> <div class="more-comment"><span class="sub-comment-count">还有<i class="count"><%=items[i].items.total-5%></i>条评论</span><span class="more-comment-btn" onclick=blogObj.loadSubComment($(this),<%=items[i].id%>) data-count=1 data-flag=true>点击查看</span> </div> <%}%> </div> <%}%> </div> <%}%> </script> </div> </div> </div> <!--评论结束--> </div> <script> </script> <div class="fr w290"> <!--作者信息开始--> <!--作者信息开始--> <div class="author-info right-fixed "> <div class="head-img"> <a href="https://blog.itpub.net/10752019/"><img src="http://account.itpub.net/api/avatar.php?uid=10752019" alt=""></a> </div> <div class="author-name"><a href="https://blog.itpub.net/10752019/">amyz</a></div> <div class="author-intro"> </div> <ul class="tree-list clearfix"> <li> <div class="item-tt">博文量</div> <a href="https://blog.itpub.net/10752019/"><span class="item-num blognum">3982</span></a> </li> <li> <div class="item-tt">访问量</div> <div class="item-num blogviewnum">7894358</div> </li> </ul> </div> <!--作者信息结束--> <script> var data = {uid: 10752019}; $._ajax({ url: '/getAuthorInfo/', data: data, type: 'get', dataType: 'json', success: function (data) { if (data.code == 200) { var data = data.data; $(".blognum").text(data.blognum); $(".blogviewnum").text(data.visitednum); } } }); </script> <!--作者信息结束--> <!--博文推荐开始--> <div class="blog-choice right-fixed"> <h3 class="choice-title">最新文章</h3> <ul class="newul"> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-1001318/" class="clearfix"> 防止关闭windows (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-1001315/" class="clearfix"> TList,AnsiString和DynamicArray的妙用 (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-1001311/" class="clearfix"> 在OpenGL中使用各异向性纹理过滤 (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-1001310/" class="clearfix"> 完成端口(上) (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-987000/" class="clearfix"> WebLogic的初步研究(2)--结构篇 (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-986998/" class="clearfix"> 玩转Windows桌面图标 (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-986997/" class="clearfix"> Dos下键盘的完全控制 ------- 一系列的BIOS级别的键盘控制函数! (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-986996/" class="clearfix"> 图像平滑滚动效果的VC实现 (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-986995/" class="clearfix"> VC++初学者常见问题解惑 (转) </a> </li> <li class="new-item"> <a href="https://blog.itpub.net/10752019/viewspace-986993/" class="clearfix"> 例程详析动态链接库 (转) </a> </li> <ul> </div> <!--大牛精选结束--> </div> </div> <div class="icon-back-top" onclick="$('html,body').animate({scrollTop:0},'slow');"></div> <!--main部分结束--> <!--百度推送--> <script> (function () { var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> <!--footer部分开始--> <div class="blog-footer"> <div class="w1200 pr"> <div class="footer-links"> <a class="icon-blog icon-wx mr30"> <div class="wx-qrcode"> <img src="/images/qrcode.jpg" alt=""> </div> </a> <a href="https://weibo.com/itpub2001?from=myfollow_all" class="icon-blog icon-wb" target="_blank"></a> </div> <p class="footer-nav"> <a href="http://www.it168.com/bottomfile/it168.shtml" target="_blank">支持我们</a> <a href="http://www.it168.com/bottomfile/tgzn.shtml" target="_blank">作者招募</a> <a href="http://www.it168.com/bottomfile/sytk.shtml" target="_blank">用户协议</a> <a href="//blog.itpub.net/31509949/viewspace-2157750/" target="_blank">FAQ</a> <a href="http://edu.itpub.net/contactus.html" target="_blank">Contact Us</a> <script src="https://s22.cnzz.com/z_stat.php?id=1274521965&web_id=1274521965" language="JavaScript"></script> <a target="_blank" href="https://www.itpub.net/editorial-standards.html" rel="nofollow">编辑准则</a> </p> <p>北京盛拓优讯信息技术有限公司. 版权所有  <a style="color:#777777;" target="_blank" href="http://beian.miit.gov.cn">京ICP备16024965号-8</a> 北京市公安局海淀分局网监中心备案编号:11010802021510 niuxiaotong@pcpop.com 17352615567 <a style="color:#777777;" target="_blank" href="http://www.it168.com/jubao.html"> 未成年人举报专区</a></p> <p>广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员</p> <p>违法和不良信息举报电话:18101376593</p> </div> </div> <!--footer部分结束--> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?5016281862f595e78ffa42f085ea0f49"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?540bee2c1a1b922df9e0a0b922440b73"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <!-- END STAT PV --> </body> </html>