2

我试图弄清楚如何根据 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 文档的格式。我可以制作以“xy”为前缀的“SlideDeck”元素以及所有其他元素,但我不想修改所有代码以另外将 uri 添加到命名空间和前缀来实现这一点。最大的症结在于 xmlns:xy 定义和 xy:type 属性,它们会提醒接收者会发生什么。其他变化是合理的。我还可以控制程序验证的 XSD,如果让它创建和验证最好通过那里的更改来完成。

4

1 回答 1

1

您的架构说该SlideDeck元素必须具有一个type属性 - 都在 null 命名空间中,而在您的 XML 中,SlideDeck元素typehttp://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>

幻灯片.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 会正确验证。

于 2013-03-19T01:34:39.317 回答