使用XML命名空间针对C#中的模式创建和验证XML

时间:2013-03-18 22:56:53

标签: c# .net xml xsd xml-namespaces

我正在试图弄清楚如何针对C#中的模式验证XML。如果XML很简单并且不使用命名空间元素,那么一切似乎都很好。但是,如果它使用XML命名空间,我就会遇到问题。

我想要生成的XML是:

<?xml version="1.0" encoding="utf-8"?>
<SlideDeck xmlns:xy="http://something.com" xy:type="SlideDefinitions">
  <Slide>...</Slide>
  <Slide>...</Slide>
  ...
</SlideDeck>

我可以在C#中用相当于:

的东西生成它
XmlDocument xDoc = new XmlDocument();
XmlElement xSlideDeck = xDoc.CreateElement("SlideDeck");
xDoc.AppendChild(xSlideDeck);

xSlideDeck.SetAttribute("xmlns:xy", "http://something.com");
xSlideDeck.SetAttribute("type", "http://something.com", "SlideDefinitions");

我可以尝试使用以下方法验证生成的XML文档:

xDoc.Schemas.Add("", "Schema.xsd");
xDoc.Validate(Handler);

要验证的Schema.xsd文件现在非常简单:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="SlideDeck">
        <xs:complexType>
            <xs:sequence>
                <xs:choice maxOccurs="unbounded">
                    <xs:element ref="Slide"/>
                </xs:choice>
            </xs:sequence>
            <xs:attribute name="type" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
    ... Slide Defined Here ...
</xs:schema>

运行验证时,我收到以下错误:

The 'http://something.com:type' attribute is not declared.
The required attribute 'type' is missing.

我还尝试在XmlDocument中添加一个附加模式,该模式使用相同的模式文件引用http://something.com(希望它可以为'xy'命名空间引入它)。我也尝试过将一个模式添加到正确的uri(省略了没有uri的模式),但是根据其他设置,没有任何验证。我已经尝试使根'SlideDeck'元素也属于http://something.com命名空间。

知道这里可能会发生什么吗?我根本无法改变XML文档的格式。我可以将'SlideDeck'元素和'xy'以及所有其他元素一起制作,但是我不想修改所有代码以额外添加uri到命名空间和前缀来实现这一点。最重要的问题是xmlns:xy定义和xy:type属性,它会提醒收件人注意什么。其他变化是合理的。我也可以控制程序验证的XSD,如果要创建和验证最好通过那里的更改来完成。

1 个答案:

答案 0 :(得分:1)

您的架构表明SlideDeck元素必须具有type属性 - 都在null命名空间中,而在XML中,SlideDeck元素具有属性type in http://something.com命名空间 - 因此错误。

您应该将XML更改为:

<SlideDeck type="SlideDefinitions">
  <Slide>. . . </Slide>
  <Slide>. . . </Slide>
  . . . 
</SlideDeck>

(即摆脱命名空间)。

在替代方案中,您必须更改架构,将其拆分为两个:

<强> typeAttr.xsd:

<xs:schema 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:xy="http://something.com" 
  xmlns="http://something.com"
  targetNamespace="http://something.com"
  elementFormDefault="qualified"
  attributeFormDefault="qualified" >

  <xs:attribute name="type" type="xs:string" />

</xs:schema>

<强> slide.xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:xy="http://something.com">
  <xs:import namespace="http://something.com" schemaLocation="typeAttr.xsd"/>
  <xs:element name="SlideDeck">
    <xs:complexType>
      <xs:sequence>
        <xs:choice maxOccurs="unbounded">
          <xs:element ref="Slide"/>
        </xs:choice>
      </xs:sequence>
      <xs:attribute ref="xy:type" use="required" />
    </xs:complexType>
  </xs:element>
  <xs:element name="Slide"></xs:element>
</xs:schema>

(在同一目录中)。

通过这种方式,您可以在其单独的命名空间中定义type属性,并且原始XML可以正确验证。