1个文件中有多个Xsd模式

时间:2015-03-25 15:05:32

标签: xml xsd xsd-validation

我有多个Xsd模式文件(小文件)并且想以某种方式将它们组合成一个大文件,我想到的是一个xml文件,每个Xsd模式内容有一个节点,在C#代码中选择相应的部分和验证它。 问题是我可以看到一个警告"全球元素' xxx'已经宣布。 "当使用Visual Studio打开Xml文件时(我绝对不是Xsd专家;我确实重复了相同的元素)。

关于这种方法的正确性的任何想法? 我可以使用CData for Xsd内容吗?

Xml文件的示例:

Xml 1:

<resource xmlns="">
  <identifier>5401902302111</identifier>
  <product>printer</product>
  <requestedby />
</resource>

Xml 2:

<resource xmlns="">
  <identifier>5401902302112</identifier>
  <email>someone@em.com</email>
</resource>

Xsd 1:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xs:element name="resource">
              <xs:complexType>
                <xs:sequence>
                  <xs:element type="xs:long" name="identifier"/>
                  <xs:element type="xs:string" name="requestedby"/>
                  <xs:element type="xs:string" name="product"/>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:schema>

Xsd 2:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xs:element name="resource">
              <xs:complexType>
                <xs:sequence>
                  <xs:element type="xs:long" name="identifier"/>
                  <xs:element type="xs:string" name="email"/>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:schema>

我最终想要的是什么:

*<?xml version="1.0" encoding="utf-8"?>
<resource>
  <resourcedata type="acquisition">
    <details>
      <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="resource">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:long" name="identifier"/>
              <xs:element type="xs:string" name="requestedby"/>
              <xs:element type="xs:string" name="product"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
    </details>
  </resourcedata>
  <resourcedata type="warningletter">
    <details>
      <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="resource">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:long" name="identifier"/>
              <xs:element type="xs:string" name="email"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
    </details>
  </resourcedata>
</data>*

C#代码:

var xsdContent =
                xDoc.Element("resource").Elements("resourcedata")
                    .Where(
                        x =>                            
                            x.Attribute("type").Value == "acquisition")
                    .FirstOrDefault().Element("details").FirstNode.ToString();            


            var doc = new XDocument(xElementContent);

            XmlSchemaSet schemas = new XmlSchemaSet();
            schemas.Add("", XmlReader.Create(new StringReader(xsdContent)));

            Console.WriteLine("Validating doc");
            bool errors = false;
            doc.Validate(schemas, (o, e) =>
            {
                Console.WriteLine("{0}", e.Message);
                Console.WriteLine("{0}", e.Exception);
                errors = true;
            });

            Console.WriteLine("doc {0}", errors ? "did not validate" : "validated");

xElementContent 变量包含Xml内容)

由于

2 个答案:

答案 0 :(得分:2)

您应该使用基于 xsd:include xsd:import 的标准方法,而不是发明自己的特殊方式来组合XSD。

另请参阅:What's the difference between xsd:include and xsd:import

除非您有非常具体的理由在代码中使用ad hoc方法调度验证,否则您应该在文档级别进行验证,并让解析器为您找到适当的声明。

答案 1 :(得分:2)

与其他人不同,我认为您的问题唯一的问题是它无法说明为什么会创建您所描述的XML文件格式的好例子。事实上,我参与了一个有趣的讨论here on SO,其中C. M. Sperberg-McQueen甚至整理了demo,结论是:

  因此,它说明了多个符合规范的模式文档   嵌入在同一个XML文档中。 (因为这似乎是一个   一些有关方面的问题,显然也应该注意到   这里没有涉及WSDL。)

我觉得有必要将CM Sperberg-McQueen的答案联系起来,因为你说 我在考虑一个xml文件 而不是一个XSD文件(这将是kjhughes点)

为什么我认为你没有表现出好的情况,因为以下单个模式可以很好地满足你的XML。

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="resource">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="identifier" type="xs:unsignedLong"/>
                <xs:choice>
                    <xs:element minOccurs="0" name="email" type="xs:string"/>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="product" type="xs:string"/>
                        <xs:element minOccurs="0" name="requestedby" type="xs:string"/>                             
                    </xs:sequence>
                </xs:choice>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

让我们看看一些情况(如果您还有其他问题,请更新您的问题):

  • 您的根元素可能具有不同的名称。在这种情况下,只需创建另一个匹配该名称的全局元素。
  • 您的根元素可能位于不同的命名空间中。在这种情况下,只需创建另一个XSD文件,targetNamespace与XML的命名空间相匹配。然后将所有XSD添加到XmlSchemaSet,然后验证。
  • 对于相同的元素,您的内容模型可能会有所不同,但可以根据XSD 1.0进行协调(因为您显示的是.NET代码库存,我假设您已经坚持使用.NET支持的内容)。这就是我上面创建的模式的情况。
  • 您无法使用XSD 1.0;它是否可以使用XSD 1.1中的功能(例如共同约束,类型替代等) - 重点是,XSD 1.1不能在这里使用。然后,您将多个XSD放在一个XML文件中的建议就像魅力一样。事实上,我认为它是.NET世界中XSD 1.1的穷人替代品......

对于后者,我建议采用略有不同的方法。我会使用XInclude将XSD链接到一个文件中 - 如果这是您的处理模型所需要的;有一个NET库here。这将允许独立创作XSD,从而确保每个XSD都有效,并使用通用编辑器(包括您的Visual Studio)。