以下帖子询问如何指示元素是其中的根元素 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应该做两件事:
似乎这个例子在#2失败了。 有什么建议吗?
答案 0 :(得分:50)
据我所知,任何全局定义的元素都可以用作根元素,而XML Schema没有用于指定根元素应该是什么的概念。
然而,你可以通过设计XML Schema来解决这个问题,这样只有一个全局定义的元素 - 那么只有这个元素才能作为根元素有效。
可在W3Schools找到此示例(标题使用命名类型) 此示例只有一个全局定义的元素,因此只有一个可能的根元素。
答案 1 :(得分:21)
并非每个人都同意它,但XML Schema无法指定根元素的事实是设计的。我们的想法是,如果<invoice>
在文档中唯一有效的情况下是有效的,那么如果它包含在其他内容中它同样有效。我们的想法是内容应该是可重用的,并且不应该允许您阻止某人使用有效内容作为更大内容的一部分。
(ID和IDREF作用于文档的事实反而违反了这个政策;但是这个语言是由一个相当大的委员会设计的。)
答案 2 :(得分:15)
<?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>
我还没有找到完整的解决方案来处理各种模式。将继续它。