验证时向 XElements 手动添加命名空间失败
Manual addition of namespace to XElements fails upon validation
我试图用我创建的 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"
标记,但这只是将验证错误更改为其他 elements/attributes。我也尝试动态地为每个属性添加一个命名空间,但验证问题仍然存在。我确定问题出在我的 xsd 文件中的某个地方,但我不知道那个问题是什么。如果对我的问题有任何想法,我们将不胜感激。
编辑:
将 elementFormDefault= "qualified"
添加到我的模式时,验证错误更改为:The 'testType' attribute is not declared.
,并伴随错误:The required attribute 'http://test.org/test.xsd:testType' is missing.
我认为这确实是由于命名空间限定,我不知道 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
,这意味着您的模式的根需要命名空间限定,但子元素不需要它。
考虑到 elementFormDefault
和 attributeFormDefault
均未设置或设置为 unqualified
,上述架构的有效 XML 实例为:
<tns:testRoot xmlns:tns="http://test.org/test.xsd">
<testObject testType="2">
<foo />
<bar />
</testObject>
</tns:testRoot>
因此,您不应将名称空间添加到每个元素,而应仅添加到根元素。
如果我不正确,请告诉我。
我试图用我创建的 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"
标记,但这只是将验证错误更改为其他 elements/attributes。我也尝试动态地为每个属性添加一个命名空间,但验证问题仍然存在。我确定问题出在我的 xsd 文件中的某个地方,但我不知道那个问题是什么。如果对我的问题有任何想法,我们将不胜感激。
编辑:
将 elementFormDefault= "qualified"
添加到我的模式时,验证错误更改为:The 'testType' attribute is not declared.
,并伴随错误:The required attribute 'http://test.org/test.xsd:testType' is missing.
我认为这确实是由于命名空间限定,我不知道 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
,这意味着您的模式的根需要命名空间限定,但子元素不需要它。
考虑到 elementFormDefault
和 attributeFormDefault
均未设置或设置为 unqualified
,上述架构的有效 XML 实例为:
<tns:testRoot xmlns:tns="http://test.org/test.xsd">
<testObject testType="2">
<foo />
<bar />
</testObject>
</tns:testRoot>
因此,您不应将名称空间添加到每个元素,而应仅添加到根元素。
如果我不正确,请告诉我。