Xsd验证问题

时间:2009-05-31 15:41:39

标签: c# xsd

我有以下(错误的)Xml:

<jobs>
    <job>
        <id>1</id>
        <state><![CDATA[IL]]></state>
    </job>
    <job>
        <id>2</id>
    </job>
</jobs>

id和state节点都是需要的项目。我为它写了一个Xsd:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="importvalidator"
    elementFormDefault="qualified"
    targetNamespace="http://foo.org/importvalidator.xsd"
    xmlns="http://foo.org/importvalidator.xsd"
    xmlns:mstns="http://foo.org/importvalidator.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="jobs">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="job" minOccurs="1" maxOccurs="unbounded">
              <xs:complexType>
                <xs:all>
                  <xs:element name="id" type="xs:string" minOccurs="1"/>
                  <xs:element name="state" type="xs:string" minOccurs="1"/>
                </xs:all>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

它仍然可以验证为结构有效的Xml。我在这里缺少什么?

Update1:​​我正在使用的代码是C#:

        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add("http://foo.org/importvalidator.xsd", "validator.xsd");

        XDocument doc = XDocument.Load(fileName);
        if (doc == null | doc.Root == null)
        {
            throw new ApplicationException("xml error: the referenced stream is not xml.");
        }

        doc.Validate(schemas, (o, e) =>
        {
            throw new ApplicationException("xsd validation error: xml file has structural problems");
        });

3 个答案:

答案 0 :(得分:3)

请格式化您的xml,以便更容易阅读 - 就像这样:

<jobs>
  <job>
    <id>1</id>
    <state><![CDATA[IL]]></state>
  </job>
  <job>
    <id>2</id>
  </job>
</jobs>

我认为你实际上并没有对它进行验证 - 命名空间意味着即使在第二个“<state>”中使用“<job>”,XML也无法验证。具体来说,XSD的目标名称空间为“http://foo.org/importvalidator.xsd”,但XML没有给出名称空间。

设置一个简单的XSD和XML测试用例,你肯定知道它会失败 - 用它来追踪你没有验证的原因。

此外,您的XSD缺少元素和架构的关闭标记,因此它应该给出错误 - 或者它只是错误粘贴: - )


您可以从架构中删除targetNamespace:

<xs:schema id="importvalidator"
    elementFormDefault="qualified"
    targetNamespace="http://foo.org/importvalidator.xsd    ← DELETE THIS"
    xmlns="http://foo.org/importvalidator.xsd"
    xmlns:mstns="http://foo.org/importvalidator.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

所以它看起来像这样:

<xs:schema id="importvalidator"
    elementFormDefault="qualified"
    xmlns="http://foo.org/importvalidator.xsd"
    xmlns:mstns="http://foo.org/importvalidator.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

PS:有人知道你是否/如何用SO的降价突出显示部分源代码?

答案 1 :(得分:2)

@ 13ren有正确的答案。如果节点与任何架构都不匹配,则不会出错。这只是一个警告。我可以在下面的代码中看到警告:

private static void ValidateDocument(XmlSchemaSet schemas, string uri)
{
    var settings = new XmlReaderSettings
                       {
                           Schemas = schemas,
                           ValidationFlags =
                               XmlSchemaValidationFlags.
                                   ProcessIdentityConstraints |
                               XmlSchemaValidationFlags.
                                   ReportValidationWarnings,
                           ValidationType = ValidationType.Schema
                       };
    settings.ValidationEventHandler += OnValidationEventHandler;
    using (var validatingReader = XmlReader.Create(uri, settings))
    {
        XDocument.Load(
            validatingReader,
            LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
    }
    return;
}

这会产生以下结果:

警告:无法找到元素“作业”的架构信息。 警告:找不到元素“作业”的架构信息。 警告:找不到元素“id”的架构信息。 警告:找不到元素“state”的架构信息。 警告:找不到元素“作业”的架构信息。 警告:找不到元素“id”的架构信息。

更改XML并再次运行:

<?xml version="1.0" encoding="utf-8" ?>
<jobs xmlns="http://foo.org/importvalidator.xsd">
  <job>
    <id>1</id>
    <state><![CDATA[IL]]></state>
  </job>
  <job>
    <id>2</id>
  </job>
</jobs>

产生您预期的错误:

错误:名称空间“http://foo.org/importvalidator.xsd”中的元素“作业”内容不完整。期望的可能元素列表:名称空间“http://foo.org/importvalidator.xsd”中的“状态”。

答案 2 :(得分:0)

您使用的解析器/语言是什么?过去,如果您使用Java,则必须告诉Xerces解析器您需要XSD验证。但在检查latest release文档后,我发现现在已经内置了验证。所以看起来版本很重要。如果您是.NET开发人员,最好检查其设置是什么。

只是好奇 - 为什么CDATA围绕你的例子中的州?没有必要,AFAIK。您甚至可以在XSD中嵌入限制,以确保只获得有效的美国州代码。

但首先要做的是 - 让模式验证。