System.Xml.XmlSchemaSet compile()填充包含的模式TargetNamespace

时间:2013-02-05 17:36:54

标签: c# xml-serialization xsd xmlschemaset

我有两个xml架构:
1)infrastructureRoot.xsd:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:mif="urn:hl7-org:v3/mif" 
  xmlns:v3="urn:hl7-org:v3" 
  xmlns:ex="urn:hl7-org/v3-example" 
  xmlns="urn:hl7-org:v3" 
  targetNamespace="urn:hl7-org:v3" 
  elementFormDefault="unqualified">
  <xs:include schemaLocation="datatypes-base.xsd"/>
  <xs:group name="InfrastructureRootElements">
    <xs:sequence>
      <xs:element name="realmCode" 
                  type="Norwegian_customer" 
                  minOccurs="0" 
                  maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:group>
  <xs:attributeGroup name="InfrastructureRootAttributes"/>
</xs:schema>

2)的数据类型-base.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:sch="http://www.ascc.net/xml/schematron"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"  
  elementFormDefault="unqualified">
  <xs:complexType name="customer">
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
      <xs:element name="country" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="Norwegian_customer">
    <xs:complexContent>
     <xs:restriction base="customer">
       <xs:sequence>
         <xs:element name="firstname" type="xs:string"/>
         <xs:element name="lastname" type="xs:string"/>
         <xs:element name="country" 
           type="xs:string" 
           fixed="Norway"/>
     </xs:sequence>
   </xs:restriction>
  </xs:complexContent>
 </xs:complexType>
</xs:schema>

我使用以下C#代码加载具有所有包含的根模式:

Func<XmlReader> xmlReaderFactory = () =>
                                        {
                                            XmlReaderSettings schemaReaderSettings = new XmlReaderSettings{ DtdProcessing = DtdProcessing.Parse};
                                                XmlTextReader reader = new XmlTextReader(@"InfrastructureRoot.xsd");
                                            return XmlReader.Create(reader, schemaReaderSettings);
                                        };

XmlSchema xsd = XmlSchema.Read(xmlReaderFactory(), (sender, eventArgs) => {});
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.ValidationEventHandler += (sender, eventArgs) => Console.WriteLine(eventArgs.Message + " " + eventArgs.Severity);

try
{
    try
    {
        XmlReaderSettings schemaReaderSettings = new XmlReaderSettings {DtdProcessing = DtdProcessing.Parse};
        XmlReader schemaReader = XmlReader.Create(new DummyReader(), schemaReaderSettings);
        schemaSet.Add(null, schemaReader);
    }
    catch
    {
        // the only thing this code is needed is to set ProhibitDTD to false
        // there is no acceptable public way to do that
    }

    schemaSet.Add(xsd);
    schemaSet.Compile();
    XmlSchemaInclude external = ((XmlSchemaInclude)xsd.Includes[0]);
    String targetNamespace = external.Schema.TargetNamespace;
    Debug.Assert(targetNamespace == null);
}
catch{}

执行后“targetNamespace”值等于“urn:hl7-org:v3”,这与原始模式“datatypes-base.xsd”不同并中断验证。有人可以帮我解决问题吗?

3 个答案:

答案 0 :(得分:2)

当具有显式目标命名空间的架构文档(如您的infrastructureRoot.xsd)使用xs:include来包含指定无目标命名空间的架构文档(如datatypes-base.xsd)时,第二个架构文档中的声明被解释为它们包含的架构文档与包含架构文档具有相同的命名空间。此机制有时称为 chameleon include - 包含的架构文档中的声明,根据上下文对此目标命名空间进行处理。

如果您希望命名空间urn:hl7-org:v3捕获复杂类型Customer和NorwegianCustomer ,那么infrastructureRoot.xsd需要使用xs:import,而不是xs:include,并且需要更改默认命名空间以使对type="Norwegian_customer"的引用成为{}Norwegian_customer的引用(即,Norwegian_customer作为其本地名称且没有命名空间的限定名称)而不是(现在是)对{urn:hl7-org:v3}Norwegian_customer的引用。

xs:import构造从不同的命名空间导入组件,而xs:include包含来自相同命名空间的组件。变色龙包含可以被视为使包含的模式文档中的组件在同一名称空间中的一种方式;如果它不存在,那么基础架构模式中的xs:include只会引发错误。

答案 1 :(得分:2)

我们一直在使用BizTalk和.Net中的HL7v3和CDA。为了使CDA模式正常工作以进行验证并发送消息,我必须在所有“coreschemas”xsd文件中添加urn:hl7-org:v3的目标名称空间。在验证工作和BizTalk消息流动之后。

我觉得将targetnamespaces添加到我并不真正拥有的模式中感觉很舒服,但这是一个不错的折衷方案,因为我从来没有真正改变模式本身,之后事情也有效。

答案 2 :(得分:0)

在导入HL7v3源到我们的自定义数据存储格式并向后导出到xml架构时发现了原始问题。第二个模式获取目标命名空间但不获取默认命名空间,这会导致验证错误。 这是第二个模式导出结果:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
 xmlns:sch="http://www.ascc.net/xml/schematron"
 xmlns="urn:hl7-org123:v3" 
 xmlns:v3="urn:hl7-org:v3"
 elementFormDefault="unqualified"
 targetNamespace="urn:hl7-org:v3"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="customer">
 <xs:sequence>
   <xs:element name="firstname" type="xs:string" />
   <xs:element name="lastname" type="xs:string" />
   <xs:element name="country" type="xs:string" />
 </xs:sequence>
</xs:complexType>
 <xs:complexType name="Norwegian_customer">
<xs:complexContent mixed="false">
  <xs:restriction base="customer">
    <xs:sequence>
      <xs:element name="firstname" type="xs:string" />
      <xs:element name="lastname" type="xs:string" />
      <xs:element fixed="Norway" name="country" type="xs:string" />
    </xs:sequence>
   </xs:restriction>
</xs:complexContent>
 </xs:complexType>
</xs:schema>

验证在限制基础属性值上失败。 根据目标模式设计说明,我们有两种可能的解决方案:

  1. 使用带有“v3”前缀的限定值。
  2. 添加默认命名空间“xmlns =”urn:hl7-org:v3“。