独上高楼网站
  •    你所在位置:首页 VS.netXMLXML经验〉在 XML 架构中使用命名空间
  • 在 XML 架构中使用命名空间
  • 作者:佚名  文章来源:http://msdn2.microsoft.com/zh-cn/default.aspx  发布日期:2007-07-07  浏览次数:740
  • 打印这篇文章
  • 本页内容

    强大工具的王国

    目标命名空间与架构位置:有何区别?

    如果首战失利

    放眼全局,立足本地

    您的命名空间是否受到限定?

    物的整体比它各个部分的总和大

    Karma Chameleon

    更多信息

    摘要:Dare Obasanjo 讨论了 W3C XML 架构的各个方面以及命名空间对它们的影响。涉及的主题包括 targetNamespaceelementFormDefault attributeFormDefault 属性以及 includeimport redefine 元素在架构中的正确用法。(13 页打印页)

    强大工具的王国

    本周末,我曾提到的在上一篇文章中订购的书架终于到货了。我没有出去购买工具,而是急切地尝试只用螺丝刀和旧鞋(用作锤子)将它组合在一起。在手上起了几个泡且花费了几个小时后,我的书架组装完毕,但是稍微有点摇晃。

    我打电话告诉妻子,我只是将某些家具组合在一起就起了几个泡时,她禁不住笑了,于是我决定继续使用基于 XML 的图书目录,以试图恢复我的尊严。

    我决定为 XML 实例创建一个架构,以便我不仅可以在构建的应用程序中检查它们的有效性,还可以根据需要使用 .NET XML 序列化中的绝佳功能,将 XML 转换为 C# 对象。

    但首先,我需要一个方便的命令行工具来执行实例文档和架构的验证。下面是我构建的用于简化此过程的工具:

    using System;

    using System.Xml;

    using System.Xml.Schema;

     

    public class XsdValidate{

     

      static XmlSchemaCollection sc = new XmlSchemaCollection();

      static string xsdFile = null;

      static string xmlFile = null;

      static string nsUri = null;

     

      static string usage = @"Usage: xsdvalidate.exe [-xml xml-file>]

       [-xsd schema-file>] [-ns namespace-uri>]

     

    Sample:  xsdvalidate.exe -xml t.xml

    Validate the XML file by loading it into XmlValidatingReader with

       ValidationType set to auto. 

     

    Sample:  xsdvalidate.exe -xml t.xml -xsd t.xsd -ns ns1

    This will validate the t.xml with the schema t.xsd with target namespace 'ns1'

     

    Sample:  xsdvalidate.exe xsd t.xsd -ns ns1

    This will validate the schema t.xsd with target namespace 'ns1'";

     

      public static void ValidationCallback(object sender, ValidationEventArgs args) {

     

        if(args.Severity == XmlSeverityType.Warning)

          Console.Write("WARNING: ");

        else if(args.Severity == XmlSeverityType.Error)

          Console.Write("ERROR: ");

     

        Console.WriteLine(args.Message); // Print the error to the screen.

      }

     

      public static void Main(string[] args){

     

        if((args.Length == 0) || (args.Length %2 != 0)){

          Console.WriteLine(usage);

          return;

        }

     

         for(int i = 0; i args.Length; i++) {

           switch(args[i]){

     

           case "-xsd":     xsdFile = args[++i];     break;

           case "-xml":     xmlFile = args[++i];     break;    

           case "-ns":    nsUri  = args[++i];     break;

     

           default:     Console.WriteLine("ERROR: Unexpected argument " + args[i]);    return;

     

           }//switch

         }//for

     

         if(xsdFile != null){      

           sc.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);

           sc.Add( nsUri, xsdFile);

           Console.WriteLine("Schema Validation Completed");

         }

     

         if(xmlFile != null){

           XmlValidatingReader vr = new XmlValidatingReader(new XmlTextReader(xmlFile));

           vr.Schemas.Add(sc);

           vr.ValidationType = ValidationType.Schema;

           vr.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);

     

           while(vr.Read());

           Console.WriteLine("Instance Validation Completed");

         }

      }//Main

    }//XsdValidate

    返回页首

    目标命名空间与架构位置:有何区别?

    我必须首先决定是否要使用目标命名空间创建架构。架构的目标命名空间指定可由该架构验证的元素和属性的命名空间。由于我上一篇文章中的实例文档使用了 urn:xmlns:25hoursaday-com:my-bookshelf 命名空间,因此实际上是选择要将该命名空间用作目标命名空间,还是在没有命名空间的情况下创建实例文档。

    假设我有效地创建了一个新的标记词汇表,并且命名空间提供了一个用来消除标记词汇表歧义的机制,我决定使用目标命名空间。这样,架构中的全局(或顶层)元素和属性声明将只引用 urn:xmlns:25hoursaday-com:my-bookshelf 命名空间的元素和属性。这同样适用于架构中的全局类型定义。下面显示的是我架构的第一行:

    xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

    targetNamespace="urn:xmlns:25hoursaday-com:my-bookshelf"

    xmlns:bk="urn:xmlns:25hoursaday-com:my-bookshelf">

                             

    我作出的第二个相关决定是在 XML 实例文档中使用架构位置。在实例文档中使用 http://www.w3.org/2001/XMLSchema-instance 命名空间的 schemaLocation noNamespaceSchemaLocation 属性,可以提供对一个或多个可用于验证文档的架构的硬编码引用。引用的架构适用于整个文档,而不仅仅是出现这些架构的元素作用域。但是,在第一次出现其命名空间名称与架构的目标命名空间相同的属性或元素之后,再指定架构位置是错误的。

    schemaLocation 属性的值是一对或更多对目标命名空间和架构位置的 URI 引用。下面是一个实例文档的代码片断,该片断使用 schemaLocation 属性来引用要用于验证该文档的架构的目标命名空间和位置:

    bk:books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:bk="urn:xmlns:25hoursaday-com:my-bookshelf"

    xsi:schemaLocation="urn:xmlns:25hoursaday-com:my-bookshelf file:///C:/books.xsd" >

                             

    noNamespaceSchemaLocation 的值是对没有目标命名空间的架构的单个 URI 引用。

    schemaLocation noNamespaceSchemaLocation 属性只是验证处理器的提示,如果您使用其他方法来为文档指定架构,则可以忽略这些提示。

    我希望在不同的计算机(可能有也可能没有 Internet 连接)上使用我的实例文档,因此决定在这些文档中使用 schemaLocation noNamespaceSchemaLocation 属性,这样对架构的硬编码引用在许多情况下将不适用。

    返回页首

    如果首战失利

    在重新考虑我的 XML 图书目录的格式后,我决定将 on-loan 属性从根元素中移除,但保持其余的格式不变。这样,假设使用上一篇文章中的以下实例文档(已稍加修改):

    ?xml version="1.0" encoding="UTF-8" ?>

    bk:books xmlns:bk="urn:xmlns:25hoursaday-com:my-bookshelf">

    bk:book publisher="IDG books" on-loan="Sanjay" >

    bk:title>XML Bible/bk:title>

    bk:author>Elliotte Rusty Harold/bk:author>

    /bk:book>

    bk:book publisher="QUE">

    bk:title>XML By Example/bk:title>

    bk:author>Benoit Marchal/bk:author>

    /bk:book>

    /bk:books>

                             

    我创建了以下架构以验证该文档及其相关内容:

    ?xml version="1.0" encoding="UTF-8" ?>

    xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

        targetNamespace="urn:xmlns:25hoursaday-com:my-bookshelf"

        xmlns:bk="urn:xmlns:25hoursaday-com:my-bookshelf">

     

     xs:element name="books">

      xs:complexType>

       xs:sequence>

        xs:element name="book" type="bk:bookType" maxOccurs="unbounded" />

       /xs:sequence>

      /xs:complexType>

     /xs:element>

     

     xs:complexType name="bookType">

      xs:sequence>

       xs:element name="title" type="xs:string" />