XML架构:根元素

以下文章询问如何指示元素是XML模式中的根元素:

是否有可能使用架构在XML文档中定义根元素?

我已经遵循了关于XML Schema的w3schools教程,但仍然不清楚。 考虑来自http://www.w3schools.com/schema/schema_example.asp的示例模式2(为方便起见,在下面转载)。 这段代码如何表示<shiporder>是根元素? 是不是说所有的元素都是有效的根元素的例子?

——————实例——————————- —

 <?xml version="1.0" encoding="ISO-8859-1"?> <shiporder orderid="889923" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="shiporder.xsd"> <orderperson>John Smith</orderperson> <shipto> <name>Ola Nordmann</name> <address>Langgt 23</address> <city>4000 Stavanger</city> <country>Norway</country> </shipto> <item> <title>Empire Burlesque</title> <note>Special Edition</note> <quantity>1</quantity> <price>10.90</price> </item> <item> <title>Hide your heart</title> <quantity>1</xample saying that all elements are valid as root elements?quantity> <price>9.90</price> </item> </shiporder> 

———————– schema ————————

 <?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- definition of simple elements --> <xs:element name="orderperson" type="xs:string"/> <xs:element name="name" type="xs:string"/> <xs:element name="address" type="xs:string"/> <xs:element name="city" type="xs:string"/> <xs:element name="country" type="xs:string"/> <xs:element name="title" type="xs:string"/> <xs:element name="note" type="xs:string"/> <xs:element name="quantity" type="xs:positiveInteger"/> <xs:element name="price" type="xs:decimal"/> <!-- definition of attributes --> <xs:attribute name="orderid" type="xs:string"/> <!-- definition of complex elements --> <xs:element name="shipto"> <xs:complexType> <xs:sequence> <xs:element ref="name"/> <xs:element ref="address"/> <xs:element ref="city"/> <xs:element ref="country"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="item"> <xs:complexType> <xs:sequence> <xs:element ref="title"/> <xs:element ref="note" minOccurs="0"/> <xs:element ref="quantity"/> <xs:element ref="price"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="shiporder"> <xs:complexType> <xs:sequence> <xs:element ref="orderperson"/> <xs:element ref="shipto"/> <xs:element ref="item" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute ref="orderid" use="required"/> </xs:complexType> </xs:element> </xs:schema> 

从我的angular度来看,XML Schema应该做两件事情:

  1. 定义每个节点内可能发生的事情
  2. 定义每个节点的放置位置

而且这个例子似乎在#2失败了。 有什么build议么?

据我所知,任何全局定义的元素都可以用作根元素,而XML Schema没有指定根元素应该是什么的概念。

但是,你可以通过很好地devise你的XML Schema来解决这个问题,所以只有一个全局定义的元素 – 那么只有这个元素是有效的根元素。

这个例子可以在W3Schoolsfind( 使用命名types的标题)这个例子只有一个全局定义的元素,因此只有一个可能的根元素。

并不是所有人都同意这一点,但XML Schema无法指定根元素的事实是有目的的。 这个想法是,如果一个<invoice>在文档中唯一的东西是有效的,那么如果它被包含在别的东西里,它也同样有效。 这个想法是内容应该是可重用的,并且不应该被允许阻止某人使用有效内容作为更大的一部分。

(ID和IDREF被限制在一个文档中的事实是违背了这个策略;但是这个语言是由一个相当大的委员会devise的)。

你是对的。 xsd应该是:

 <?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- definition of attributes --> <xs:attribute name="orderid" type="xs:string"/> <!-- definition of complex elements --> <xs:complexType name="shiptoType"> <xs:sequence> <xs:element name="name" type="xs:string" /> <xs:element name="address" type="xs:string" /> <xs:element name="city" type="xs:string" /> <xs:element name="country" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:complexType name="itemType"> <xs:sequence> <xs:element name="title" type="xs:string" /> <xs:element name="note" minOccurs="0" type="xs:string" /> <xs:element name="quantity" type="xs:string" /> <xs:element name="price" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:element name="shiporder"> <xs:complexType> <xs:sequence> <xs:element name="orderperson" type="xs:string" /> <xs:element name="shipto" type="shiptoType"/> <xs:element name="item" maxOccurs="unbounded" type="itemType"/> </xs:sequence> <xs:attribute ref="orderid" use="required"/> </xs:complexType> </xs:element> </xs:schema> 

正如你所看到的,现在只有一个xs:element ,而且这是唯一可以成为有效根元素的元素:)

许多全球性因素的缺点是它们都可以作为文件的根源。 好处是你可以在定义新的types时使用元素,这将确保子元素的名称空间与父types的名称空间匹配。

我已经改变了,认为只应该有一个全球元素,所有复杂的types应该有一个全球性的元素。

这段代码如何表明是根元素?

John,那个模式刚刚定义了所有的元素,其中的任何一个都可以作为一个根元素来select。 如果您尝试从Altova XML Spy之类的任何工具生成示例xml,您将会select一个元素作为根元素。

所以这些元素中的任何一个都可以成为根。

为了避免歧义,使用一个全局定义的元素。

根据您提供的示例,可以find唯一的根元素。

你可以得到一个全局元素列表,然后得到一个在节点xs:sequence下的complexType中引用的嵌套元素的列表,因此根元素是全局元素列表中的元素,而不是嵌套元素列表中的元素。

我已经通过在.NET中使用XmlSchemaSet类来完成此操作。 这里是代码片段:

 var localSchema = schemaSet.Schemas().OfType<XmlSchema>().Where(x => !x.SourceUri.StartsWith("http")).ToList(); var globalComplexTypes = localSchema .SelectMany(x => x.Elements.Values.OfType<XmlSchemaElement>()) .Where(x => x.ElementSchemaType is XmlSchemaComplexType) .ToList(); var nestedTypes = globalComplexTypes.Select(x => x.ElementSchemaType) .OfType<XmlSchemaComplexType>() .Select(x => x.ContentTypeParticle) .OfType<XmlSchemaGroupBase>() .SelectMany(x => x.GetNestedTypes()) .ToList(); var rootElement= globalComplexTypes.Single(x => !nestedTypes.Select(y => y.ElementSchemaType.QualifiedName).Contains(x.SchemaTypeName)); 

扩展方法GetNestedTypes:

 static IEnumerable<XmlSchemaElement> GetNestedTypes(this XmlSchemaGroupBase xmlSchemaGroupBase) { if (xmlSchemaGroupBase != null) { foreach (var xmlSchemaObject in xmlSchemaGroupBase.Items) { var element = xmlSchemaObject as XmlSchemaElement; if (element != null) yield return element; else { var group = xmlSchemaObject as XmlSchemaGroupBase; if (group != null) foreach (var item in group.GetNestedTypes()) yield return item; } } } } 

但是在使用这种方法时,一般的xsd仍然有问题。 例如,在Visual Studio用于configuration文件的DotNetConfig.xsd中,根元素定义如下:

  <xs:element name="configuration"> <xs:complexType> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:any namespace="##any" processContents="lax" /> </xs:choice> <xs:anyAttribute namespace="http://schemas.microsoft.com/XML-Document-Transform" processContents="strict"/> </xs:complexType> </xs:element> 

我还没有find一个完整的解决scheme来处理各种模式。 将继续下去。