XML Schema:根元素

时间:2012-01-13 16:48:27

标签: xml xsd

以下帖子询问如何指示元素是其中的根元素 XML架构:

Is it possible to define a root element in an XML Document using Schema?

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

------------------ instance ---------------------------- ------

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

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

  1. 定义每个节点内可能发生的事情
  2. 定义每个节点的放置位置
  3. 似乎这个例子在#2失败了。 有什么建议吗?

6 个答案:

答案 0 :(得分:50)

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

然而,你可以通过设计XML Schema来解决这个问题,这样只有一个全局定义的元素 - 那么只有这个元素才能作为根元素有效。

可在W3Schools找到此示例(标题使用命名类型) 此示例只有一个全局定义的元素,因此只有一个可能的根元素。

答案 1 :(得分:21)

并非每个人都同意它,但XML Schema无法指定根元素的事实是设计的。我们的想法是,如果<invoice>在文档中唯一有效的情况下是有效的,那么如果它包含在其他内容中它同样有效。我们的想法是内容应该是可重用的,并且不应该允许您阻止某人使用有效内容作为更大内容的一部分。

(ID和IDREF作用于文档的事实反而违反了这个政策;但是这个语言是由一个相当大的委员会设计的。)

答案 2 :(得分:15)

是的,你是对的。 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,而且那个是唯一一个可以成为有效根元素的人:)

答案 3 :(得分:1)

许多全局元素的缺点是它们都可以用作文档的根元素。这样做的好处是可以在定义新类型时使用该元素,这将确保子元素的名称空间与父类型的名称空间匹配。

我已经改变了认为应该只有一个全局元素,所有复杂类型都应该有一个全局元素。

答案 4 :(得分:0)

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

约翰, 该模式只定义了所有元素,其中任何元素都可以选择作为根元素。如果您尝试从Altova XML Spy或其类型的任何工具生成示例xml,您将选择一个元素作为根元素。

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

为防止歧义,请使用一个全局定义的元素。

答案 5 :(得分:0)

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

您可以获取全局元素列表,然后获取在节点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用于配置文件的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>

我还没有找到完整的解决方案来处理各种模式。将继续它。