在验证时,手动将命名空间添加到XElements失败

时间:2015-01-22 02:37:37

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

我正在尝试使用我创建的xsd文件验证一组XML标记,添加的约束条件是所有XElement必须属于命名空间。

<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.

1 个答案:

答案 0 :(得分: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'

表示验证器需要&#39; testObject&#39;在&#39; http://test.org/test.xsd&#39;中收到它时没有名称空间。命名空间。

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

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

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

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

如果我不对,请告诉我。