正确的使用方法在XSD关键 [英] Correct way to use key in xsd

查看:143
本文介绍了正确的使用方法在XSD关键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个项目我工作的XSD架构。下面的架构是一个我从微软的例子了,并略作修改。

我想使用的关键和keyref声明一个独特的键一组项目,然后引用另一个段是关键。

我无法得到它的工作很长一段时间。我会写的模式,并设置一个测试文档,应验证失败,因为(1)重复引用不存在的键键和(2)refkeys但它一直传递。

一堆修修补补和工作过的一个例子后,我得到它的工作。所以,我试图缩小它在这个例子是什么工作,但被使其不能在我原来的尝试工作。

我验证使用.net的XmlDocument和的XmlSchema。我会贴上我的测试验证code底部。

我的问题是,为什么在关键的工作,如果声明,因为它是低于但如果声明,因为它是在注释工作?

XSD:

 < XS:模式的xmlns:XS =htt​​p://www.w3.org/2001/XMLSchema
      目标名称=namespace1
      的xmlns =namespace1
      XMLNS:R =namespace1
      将elementFormDefault =合格>

< XS:元素的名称=根>
  < XS:复杂类型>
    < XS:序列>
      < XS:元素的名称=A型=R:atype的maxOccurs为=无界>
        < XS:keyref名=假是指=R:pNumKey>
          < XS:选择的XPath =部分/>
          < XS:现场的xpath =@参考号/>
        < / XS:keyref>
      < / XS:组件>
      < XS:元素的名称=B型=R:B型/>
    < / XS:序列>
  < / XS:复杂类型>

  <  - !这工作。 - >
  < XS:键名称=pNumKey>
    < XS:选择的XPath =△:B / R:部分/>
    < XS:现场的xpath =@键号/>
  < / XS:键>
  <! - 
  这是行不通的。

  < XS:键名称=pNumKey>
    < XS:选择的XPath =B /一部分/>
    < XS:现场的xpath =@键号/>
  < / XS:键>
   - >
< / XS:组件>

< XS:复杂类型的名称=atype的>
  < XS:序列>
    < XS:元素的名称=部分的maxOccurs =无界>
      < XS:复杂类型>
        < XS:简单文本>
          < XS:扩展底座=XS:字符串>
            < XS:属性名=参考号类型=XS:整数/>
          < / XS:扩展>
        < / XS:简单文本>
      < / XS:复杂类型>
    < / XS:组件>
  < / XS:序列>
< / XS:复杂类型>

< XS:复杂类型的名称=B型>
  < XS:序列>
    < XS:元素的名称=部分的maxOccurs =无界>
      < XS:复杂类型>
        < XS:属性名=键号类型=XS:整数/>
      < / XS:复杂类型>
    < / XS:组件>
  < / XS:序列>
< / XS:复杂类型>
< / XS:模式>
 

Vaidation code:

 私有静态无效ValidateXml(根弦,弦xsdFileName,串xmlFileName)
    {
        的ValidationEventHandler辆=新的ValidationEventHandler(Program_ValidationEventHandler);
        的XmlSchema模式= XmlSchema.Read(新的XmlTextReader(根+ xsdFileName),辆);

        XmlDocument的XDOC =新的XmlDocument();
        XmlReaderSettings设置=新XmlReaderSettings();
        settings.Schemas.Add(架构);

        settings.ValidationType = ValidationType.Schema;

        settings.ValidationEventHandler + =
            新的ValidationEventHandler(Program_ValidationEventHandler);

        XmlReader的读者= XmlReader.Create(根+ xmlFileName,设置);

        xdoc.Load(读卡器);

        Console.WriteLine(xdoc.SchemaInfo.Validity);
    }

    私有静态无效Program_ValidationEventHandler(对象发件人,ValidationEventArgs E)
    {
        Console.WriteLine(的String.Format( - 消息:{0},e.Message));
    }
 

解决方案

我不是100%肯定,但我的pretty的信心的猜测是,XPath的前pression在选择元素不关心目标命名空间,只要你有的xmlns声明的命名空间属性。所以,既然你还没有宣布一个默认的命名空间,它试图以确保没有命名空间的元素部分是唯一的。而且,由于部分文档中的元素似乎是在 namespace1 命名空间,你没有任何部分中没有名称空间的元素,所以这个唯一性约束成功。

您可以通过添加到您模式元素验证了我的猜测属性的xmlns =namespace1。 (因为你的模式文档中的所有元素都prefixes,这是你需要做的唯一的事情。)如果您注释掉元素的作品,然后,该似乎是正确的解释。

编辑:好吧,我找到了答案。事实证明,在XPath 1.0中,当你有一个非prefixed的名字,它是PTED在没有命名空间是自动跨$ P $。有没有办法来设置XPath 1.0中默认的命名空间,所以你总是需要preFIX中的XPath EX pressions所有的名字,当他们在一些空间。所以,无论你声明在你的模式文档默认名称空间,注释掉定义正试图在没有命名空间匹配的名称,这不符合您的文档

I'm writing an XSD schema for a project I'm working on. The schema below is one I took from a microsoft example and modified slightly.

I am trying to use the key and keyref to declare a unique key for one set of items and then refer to that key in another section.

I couldn't get it to work for a long time. I would write the schema and setup a test doc which should fail validation because of (1) duplicate keys and (2) refkeys that refer to non-existant keys but it kept passing.

After a bunch of tinkering and working off of an example, I got it to work. So I tried to narrow it down to what worked in the example but was causing it to not work in my original attempt.

I am validating using the .NET XmlDocument and XmlSchema. I'll paste my test validation code at the bottom.

My question is, why does the key work if declared as it is below but not work if declared as it is in the comment?

XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
      targetNamespace="namespace1"
      xmlns="namespace1"
      xmlns:r="namespace1"
      elementFormDefault="qualified">  

<xs:element name="root">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="A" type="r:AType" maxOccurs="unbounded">
        <xs:keyref name="dummy" refer="r:pNumKey">
          <xs:selector xpath="part"/>
          <xs:field xpath="@ref-number"/>
        </xs:keyref>
      </xs:element>
      <xs:element name="B" type="r:BType"/>
    </xs:sequence>
  </xs:complexType>

  <!-- This works. -->
  <xs:key name="pNumKey">
    <xs:selector xpath="r:B/r:part"/>
    <xs:field xpath="@key-number"/>
  </xs:key>
  <!--
  This doesn't work.

  <xs:key name="pNumKey">
    <xs:selector xpath="B/part"/>
    <xs:field xpath="@key-number"/>
  </xs:key>
  -->
</xs:element>

<xs:complexType name="AType">
  <xs:sequence>
    <xs:element name="part" maxOccurs="unbounded">
      <xs:complexType>
        <xs:simpleContent>
          <xs:extension base="xs:string">
            <xs:attribute name="ref-number" type="xs:integer"/>
          </xs:extension>
        </xs:simpleContent>
      </xs:complexType>
    </xs:element>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="BType">
  <xs:sequence>
    <xs:element name="part" maxOccurs="unbounded">
      <xs:complexType>
        <xs:attribute name="key-number" type="xs:integer"/>
      </xs:complexType>
    </xs:element>
  </xs:sequence>
</xs:complexType>
</xs:schema>

Vaidation Code:

    private static void ValidateXml(string root, string xsdFileName, string xmlFileName)
    {
        ValidationEventHandler veh = new ValidationEventHandler(Program_ValidationEventHandler);
        XmlSchema schema = XmlSchema.Read(new XmlTextReader(root + xsdFileName), veh);

        XmlDocument xdoc = new XmlDocument();
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Schemas.Add(schema);

        settings.ValidationType = ValidationType.Schema;

        settings.ValidationEventHandler +=
            new ValidationEventHandler(Program_ValidationEventHandler);

        XmlReader reader = XmlReader.Create(root + xmlFileName, settings);

        xdoc.Load(reader);

        Console.WriteLine(xdoc.SchemaInfo.Validity);
    }

    private static void Program_ValidationEventHandler(object sender, ValidationEventArgs e)
    {
        Console.WriteLine(string.Format("-Message:{0}", e.Message));
    }

解决方案

I'm not 100 % sure, but my pretty confident guess is that the XPath expression in the selector element does not care about the target namespace, just the namespaces you've declared with xmlns attributes. So, since you haven't declared a default namespace, it tries to ensure elements part in no namespace are unique. And since the part elements in your document seem to be in the namespace1 namespace, you don't have any part elements in no namespace, so this uniqueness constraint succeeds.

You can verify my guess by adding to your schema element the attribute xmlns="namespace1". (Since all your elements in the schema document have prefixes, this is the only thing you need to do.) If your commented-out key element works then, this would seem to be the correct explanation.

EDIT: Okay, I found the answer. Turns out that, in XPath 1.0, when you have a non-prefixed name, it is automatically interpreted as being in no namespace. There is no way to set the default namespace in XPath 1.0, so you always need to prefix all names in XPath expressions when they are in some namespace. So no matter whether you've declared a default namespace in your schema document, the commented out key definition is trying to match names in no namespace, which doesn't match your document.

这篇关于正确的使用方法在XSD关键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆