【问题标题】:Manual addition of namespace to XElements fails upon validation验证时手动向 XElements 添加命名空间失败
【发布时间】:2015-01-23 19:18:54
【问题描述】:

我试图用我创建的 xsd 文件验证我拥有的一组 XML 标记,添加了所有 XElement 必须属于命名空间的约束。 p>

<xs:schema id="TestSchema"
  targetNamespace="http://test.org/test.xsd"
  xmlns="http://test.org/test.xsd"
  xmlns:mstns="http://test.org/test.xsd"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  >

<xs:element name="testRoot">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="testObject">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="foo" />
            <xs:element name="bar" />
          </xs:sequence>
          <xs:attribute name="testType" type="xs:int" use="required" />
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>

/xs:schema>

... 我开头的 XML 如下所示:

<testRoot>
  <testObject testType="2">
    <foo />
    <bar />
  </testObject>
</testRoot>

任何可能源于元素声明语法的问题都是因为它被简化了;有趣的是,当我不费心尝试将命名空间添加到元素时,XML 会针对此架构进行验证。

将 XML 解析为 LINQ to XML 后,我使用扩展方法为每个元素添加命名空间:

public static void SetDefaultXmlNamespace(this XElement element, XNamespace ns)
{
    foreach (var item in element.DescendantsAndSelf())
    {
        item.Name = ns.GetName(item.Name.LocalName);
    }
}

但我验证此架构的尝试没有成功。尝试根据上述 XML 创建和验证会产生一个神秘的错误:

The element 'testRoot' in namespace 'http://test.org/test.xsd' has invalid child element 'testObject' in namespace 'http://test.org/test.xsd'. List of possible elements expected: 'testObject'.

我希望这样一个简单的例子能够成功,但我显然遗漏了一些东西。

我尝试通过将有问题的 XElement 树转换为 XDocument 然后进行验证来进行验证:

string xsdMarkup = "schema here";
XElement testRoot; // declared elsewhere
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(AppStateXmlMapper.SchemaNamespace, XmlReader.Create(new StringReader(xsdMarkup)));

XDocument xmlDoc = new XDocument(testRoot);
xmlDoc.Root.SetDefaultXmlNamespace(AppStateXmlMapper.Ns);
List<string> errorList = new List<string>();

// attempt validation
xmlDoc.Validate(schemas, (sender, args) =>
{
    errorList.Add(args.Message);
});

可能值得注意的是,我尝试向架构添加约束,例如 elementFormDefault= "qualified"attributeFormDefault="qualified" 标记,但这只是将验证错误更改为其他元素/属性。我也尝试动态为每个属性添加命名空间,但验证问题仍然存在。我确定问题出在我的 xsd 文件中,但我不知道那个问题是什么。对我的问题的任何想法将不胜感激。

编辑:

elementFormDefault= "qualified" 添加到我的架构时,验证错误更改为:The 'testType' attribute is not declared.,并伴随错误:The required attribute 'http://test.org/test.xsd:testType' is missing.

【问题讨论】:

    标签: c# xml xsd linq-to-xml


    【解决方案1】:

    我认为这确实是由于命名空间限定,我不知道 LINQ 但似乎错误:

    The element 'testRoot' in namespace 'http://test.org/test.xsd' has nvalid child element 'testObject' in namespace 'http://test.org/test.xsd'. List of possible elements expected: 'testObject'

    表示验证器期望“testObject”在“http://test.org/test.xsd”命名空间中接收到它时不在命名空间中。

    ElementFormDefault 默认为unqualified,这意味着架构的根需要命名空间限定,但子元素不需要它。

    考虑到 elementFormDefaultattributeFormDefault 均未设置或设置为 unqualified,上述架构的有效 XML 实例将是:

    <tns:testRoot xmlns:tns="http://test.org/test.xsd">
      <testObject testType="2">
        <foo />
        <bar />
      </testObject>
    </tns:testRoot>
    

    因此,您不应将命名空间添加到每个元素,而应仅添加到根元素。

    如果我不正确,请告诉我。

    【讨论】:

    • 我通常会同意你的观点,因为这在逻辑上是有道理的,但是当我将elementFormDefault="qualified" 添加到 xsd 文件时,我会遇到属性验证错误。请参阅我的后续编辑:(
    • 此外,我通常同意您的观点,即上述架构并将FormDefault 属性留给unqualified 应该正确验证,但在我的后续编辑中会发生相同的验证错误。最后,我的限制是所有子元素都必须包含命名空间,因此我将命名空间附加到所有子元素的代码在理论上是所需的。
    • 如果你明确声明 attributeFormDefault='unqualified' 怎么办?否则,对 LINQ 更有经验的人可能会知道这里发生了什么.. :-/
    • 这确实是个问题。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 2015-03-12
    相关资源
    最近更新 更多