問題描述
我正在為我正在進行的項目編寫 XSD 架構.下面的架構是我從一個 microsoft 示例中獲取并稍作修改的架構.
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.
我正在嘗試使用 key 和 keyref 為一組項目聲明唯一鍵,然后在另一部分中引用該鍵.
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.
很長一段時間我都無法讓它工作.我會編寫架構并設置一個測試文檔,該文檔應該驗證失敗,因為(1)重復鍵和(2)引用不存在鍵但它一直通過的 refkeys.
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.
我正在使用 .NET XmlDocument 和 XmlSchema 進行驗證.我將在底部粘貼我的測試驗證代碼.
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>
驗證碼:
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));
}
推薦答案
我不是 100% 確定,但我相當有把握的猜測是 selector
元素中的 XPath 表達式并不關心目標命名空間,只是您使用 xmlns
屬性聲明的命名空間.因此,由于您沒有聲明默認命名空間,它會嘗試確保沒有命名空間中的元素 part
是唯一的.由于文檔中的 part
元素似乎位于 namespace1
命名空間中,因此在任何命名空間中都沒有任何 part
元素,所以這個唯一性約束成功了.
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.
您可以通過將屬性 xmlns="namespace1"
添加到您的 schema
元素來驗證我的猜測.(因為架構文檔中的所有元素都有前綴,所以這是您唯一需要做的事情.)如果您的注釋掉的 key
元素有效,那么這似乎是正確的解釋.
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.
好的,我找到了答案.事實證明,在 XPath 1.0 中,當您有一個不帶前綴的名稱時,它會被自動解釋為不在命名空間中.在 XPath 1.0 中無法設置默認名稱空間,因此當 XPath 表達式中的所有名稱位于某個名稱空間中時,您總是需要為其添加前綴.因此,無論您是否在架構文檔中聲明了默認命名空間,注釋掉的 key
定義都會嘗試匹配沒有命名空間中的名稱,這與您的文檔不匹配.
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 中使用密鑰的正確方法的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!