2010-07-29 131 views
2

我需要用新元素扩展现有XML文档,而不会失去根据未定义的原始模式和由我定义的扩展模式验证它的能力。从现有模式扩展复杂类型

例如,可以说我想CodePrice元素添加到现有Book文件,内容如下:

<aa:Book xmlns:aa="http://www.aa.com" 
     xmlns:bb="http://www.bb.com"> 
    <aa:Title>Complete Works</aa:Title> 
    <aa:Author>Shakespeare</aa:Author> 
    <bb:Code>98</bb:Code> 
    <bb:Price>31.6</bb:Price> 
</aa:Book> 

原来的架构(我不能改变)将是这个样子:

<xs:schema targetNamespace="http://www.aa.com" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns="http://www.aa.com" 
      elementFormDefault="qualified"> 
    <xs:element name="Book" type="Book--type" /> 
    <xs:complexType name="Book--type"> 
    <xs:sequence> 
     <xs:element name="Title" type="xs:string" /> 
     <xs:element name="Author" type="xs:string" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

我将如何创建一个定义这些新元素的新架构,以使包含这两个架构的SchemaSet可以成功验证上述扩展XML文档?

我试过如下常用复杂类型的扩展模式:

<xs:schema targetNamespace="http://www.bb.com" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns="http://www.bb.com" 
      xmlns:aa="http://www.aa.com" 
      elementFormDefault="qualified"> 
    <xs:import namespace="http://www.aa.com" /> 
    <xs:complexType name="Book--type"> 
    <xs:complexContent> 
     <xs:extension base="aa:Book--type"> 
     <xs:sequence> 
      <xs:element name="Code" type="xs:int" /> 
      <xs:element name="Price" type="xs:double" /> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 
</xs:schema> 

然而这会导致错误,指出元素aa:Book没有定义子元素bb:Code,这非常有意义。

这甚至可能吗?

供参考,在这里是我使用来验证文档代码:

var fail = new ValidationEventHandler((sender, e) => Debug.Fail(e.Message)); 
var schemaSet = new XmlSchemaSet(); 
schemaSet.Add(XmlSchema.Read(new StringReader(original), fail)); 
schemaSet.Add(XmlSchema.Read(new StringReader(extension), fail)); 
var settings = new XmlReaderSettings 
    { 
     ValidationType = ValidationType.Schema, 
     Schemas = schemaSet 
    }; 
settings.ValidationEventHandler += fail; 
using (var stream = File.OpenRead(fileName)) 
using (var reader = XmlReader.Create(stream, settings)) 
{ 
    while (reader.Read()) {} 
} 

回答

1

原来,xs:redefine是我一直在寻找的。它允许您重新定义新模式中的现有元素,而无需触摸原始模式或正在验证的文档。

用我原来的例子,一本书可以使用以下两种模式进行扩展:

<xs:schema targetNamespace="http://www.bb.com" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns="http://www.bb.com" 
      elementFormDefault="qualified"> 
    <xs:element name="Code" type="xs:int" /> 
    <xs:element name="Price" type="xs:double" /> 
</xs:schema> 

<xs:schema targetNamespace="http://www.aa.com" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns="http://www.aa.com" 
      xmlns:bb="http://www.bb.com" 
      elementFormDefault="qualified"> 
    <xs:import namespace="http://www.bb.com" /> 
    <xs:redefine schemaLocation="http://www.aa.com"> 
    <xs:complexType name="Book--type"> 
     <xs:complexContent> 
     <xs:extension base="Book--type"> 
      <xs:sequence> 
      <xs:element ref="bb:Code" /> 
      <xs:element ref="bb:Price" /> 
      </xs:sequence> 
     </xs:extension> 
     </xs:complexContent> 
    </xs:complexType> 
    </xs:redefine> 
</xs:schema> 
0

的问题是,即使你有你的模式B中定义一个新的类型,你的样品中的根元素文档是Book--type类型从原来的模式A.

您需要在文档中使用类型覆盖,像这样:

<aa:Book xmlns:aa="http://www.aa.com" 
     xmlns:bb="http://www.bb.com" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:type="bb:Book--type"> 
    <aa:Title>Complete Works</aa:Title> 
    <aa:Author>Shakespeare</aa:Author> 
    <bb:Code>98</bb:Code> 
    <bb:Price>31.6</bb:Price> 
</aa:Book> 
+0

可惜我不能更改文件或者被验证!幸运的是,我发现了xs:重新定义了它看起来正是我所需要的。 – 2010-08-02 11:14:46