尝试为此示例XML设计XSD架构。从外部API,所以无法改变它。我遇到的问题是如何限制行的属性。
<?xml version='1.0' encoding='UTF-8'?>
<eveapi version="2">
<currentTime>2014-04-21 06:07:26</currentTime>
<result>
<characterID>123</characterID>
<name>Me</name>
<rowset name="skills" key="typeID" columns="typeID,skillpoints,level,published">
<row typeID="3424" skillpoints="16000" level="3" published="1" />
<row typeID="3318" skillpoints="2829" level="2" published="1" />
<row typeID="3425" skillpoints="2829" level="2" published="1" />
<row typeID="3451" skillpoints="500" level="1" published="1" />
</rowset>
<rowset name="certificates" key="certificateID" columns="certificateID">
<row certificateID="1"/>
</rowset>
<rowset name="corporationRoles" key="roleID" columns="roleID,roleName">
<row roleID="1" roleName="roleDirector" />
</rowset>
<rowset name="corporationRolesAtHQ" key="roleID" columns="roleID,roleName">
<row roleID="1" roleName="roleDirector" />
</rowset>
<rowset name="corporationRolesAtBase" key="roleID" columns="roleID,roleName">
<row roleID="1" roleName="roleDirector" />
</rowset>
<rowset name="corporationRolesAtOther" key="roleID" columns="roleID,roleName">
<row roleID="1" roleName="roleDirector" />
</rowset>
<rowset name="corporationTitles" key="titleID" columns="titleID,titleName">
<row titleID="1" titleName="Member" />
<row titleID="2" titleName="Member Senior" />
<row titleID="8192" titleName="Research Director" />
</rowset>
</result>
<cachedUntil>2014-04-21 12:04:26</cachedUntil>
</eveapi>
我从基于样本的IDE生成中得到了这个。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="eveapi" type="eveapiType"/>
<xs:complexType name="rowType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="typeID" use="optional"/>
<xs:attribute type="xs:string" name="skillpoints" use="optional"/>
<xs:attribute type="xs:string" name="level" use="optional"/>
<xs:attribute type="xs:string" name="published" use="optional"/>
<xs:attribute type="xs:string" name="certificateID" use="optional"/>
<xs:attribute type="xs:string" name="roleID" use="optional"/>
<xs:attribute type="xs:string" name="roleName" use="optional"/>
<xs:attribute type="xs:string" name="titleID" use="optional"/>
<xs:attribute type="xs:string" name="titleName" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="rowsetType">
<xs:sequence>
<xs:element type="rowType" name="row" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="optional"/>
<xs:attribute type="xs:string" name="key" use="optional"/>
<xs:attribute type="xs:string" name="columns" use="optional"/>
</xs:complexType>
<xs:complexType name="eveapiType">
<xs:sequence>
<xs:element type="xs:string" name="currentTime"/>
<xs:element type="resultType" name="result"/>
<xs:element type="xs:string" name="cachedUntil"/>
</xs:sequence>
<xs:attribute type="xs:string" name="version"/>
</xs:complexType>
<xs:complexType name="resultType">
<xs:sequence>
<xs:element type="xs:string" name="characterID"/>
<xs:element type="xs:string" name="name"/>
<xs:element type="rowsetType" name="rowset" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
但它只是合并属性,因此<row>
允许任何或所有属性,无论<rowset>
。
任何帮助都会很棒,因为我已经尝试了所有我能想到的东西,并且大多数都在XSD验证器中给出了关于使用抽象错误或在某处不确定的错误。
我仍然对仅使用XSD的解决方案感兴趣,但是为了防止其他人遇到类似的问题而发现这个问题,我将使用XSL样式表/转换和XSD来解决这个问题。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
version="1.0"
encoding="utf-8"
omit-xml-declaration="no"
standalone="no"
indent="yes"/>
<xsl:template match="rowset">
<xsl:choose>
<xsl:when test="@name">
<xsl:element name="{@name}">
<xsl:copy-of select="@key"/>
<xsl:copy-of select="@columns"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
结果最终看起来像这样:
<?xml version='1.0' encoding='UTF-8'?>
<eveapi version="2">
<currentTime>2014-04-21 06:07:26</currentTime>
<result>
<characterID>123</characterID>
<name>Me</name>
<skills key="typeID" columns="typeID,skillpoints,level,published">
<row typeID="3424" skillpoints="16000" level="3" published="1" />
<row typeID="3318" skillpoints="2829" level="2" published="1" />
<row typeID="3425" skillpoints="2829" level="2" published="1" />
<row typeID="3451" skillpoints="500" level="1" published="1" />
</skills>
<certificates key="certificateID" columns="certificateID">
<row certificateID="1"/>
</certificates>
<corporationRoles key="roleID" columns="roleID,roleName">
<row roleID="1" roleName="roleDirector" />
</corporationRoles>
<corporationRolesAtHQ key="roleID" columns="roleID,roleName">
<row roleID="1" roleName="roleDirector" />
</corporationRolesAtHQ>
<corporationRolesAtBase key="roleID" columns="roleID,roleName">
<row roleID="1" roleName="roleDirector" />
</corporationRolesAtBase>
<corporationRolesAtOther key="roleID" columns="roleID,roleName">
<row roleID="1" roleName="roleDirector" />
</corporationRolesAtOther>
<corporationTitles key="titleID" columns="titleID,titleName">
<row titleID="1" titleName="Member" />
<row titleID="2" titleName="Member Senior" />
<row titleID="8192" titleName="Research Director" />
</corporationTitles>
</result>
<cachedUntil>2014-04-21 12:04:26</cachedUntil>
</eveapi>
快速解释它的作用是替换任何具有rowset
属性且元素等于属性值的name
元素,并将剩余的属性复制到新元素。它将与我需要的递归rowset
一起使用,有些可能不包含子元素上的名称,因此在这种情况下只需使用常规元素副本就可以处理它。其余的是简单的标准树拷贝。现在XML已经转换,XSD很容易制作,在我的情况下,我的IDE甚至可以为我制作它们; - )
答案 0 :(得分:0)
转换使其变得更加容易,并且由于您现在拥有不同的类型,因此可以使用XSD 1.0解决问题。
您可以生成XSD,但稍后手动编辑它是有用的,这样您就可以决定所有文件的实际规则是什么,因为该代可以生成可能过于通用的XSD或太具体了(因为它只使用一个文件作为来源)。
这是一个经过编辑的XSD,它将验证您发布的第二个XML:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="eveapi" type="eveapiType"/>
<xs:complexType name="eveapiType">
<xs:sequence>
<xs:element type="xs:string" name="currentTime"/>
<xs:element type="ResultType" name="result"/>
<xs:element type="xs:string" name="cachedUntil"/>
</xs:sequence>
<xs:attribute type="xs:string" name="version"/>
</xs:complexType>
<xs:complexType name="ResultType">
<xs:sequence>
<xs:element type="xs:string" name="characterID"/>
<xs:element type="xs:string" name="name"/>
<xs:element type="SkillsType" name="skills"/>
<xs:element type="CertificatesType" name="certificates"/>
<xs:element type="CorporationRolesType" name="corporationRoles"/>
<xs:element type="CorporationRolesType" name="corporationRolesAtHQ"/>
<xs:element type="CorporationRolesType" name="corporationRolesAtBase"/>
<xs:element type="CorporationRolesType" name="corporationRolesAtOther"/>
<xs:element type="CorporationTitlesType" name="corporationTitles"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="RowSetType">
<xs:attribute name="key" type="xs:NMTOKEN"/>
<xs:attribute name="columns" type="xs:string" />
</xs:complexType>
<xs:complexType name="SkillsType">
<xs:complexContent>
<xs:extension base="RowSetType">
<xs:sequence>
<xs:element name="row" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="typeID" type="xs:string"/>
<xs:attribute name="skillpoints" type="xs:integer"/>
<xs:attribute name="level" type="xs:integer"/>
<xs:attribute name="published" type="xs:integer"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CertificatesType">
<xs:complexContent>
<xs:extension base="RowSetType">
<xs:sequence>
<xs:element name="row" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="certificateID" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CorporationRolesType">
<xs:complexContent>
<xs:extension base="RowSetType">
<xs:sequence>
<xs:element name="row" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="roleID" type="xs:string"/>
<xs:attribute name="roleName" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CorporationTitlesType">
<xs:complexContent>
<xs:extension base="RowSetType">
<xs:sequence>
<xs:element name="row" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="titleID" type="xs:string"/>
<xs:attribute name="titleName" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
如果您正在设计此XSD,您可以改进许多内容。使用可以按上下文区分的id
和name
等常用名称,而不是roleID
和roleName
,可以让您更多地重复使用类型。您还可以使用标准符号表示日期/时间,例如
<currentTime>2014-04-21T06:07:26</currentTime>
而不是
<currentTime>2014-04-21 06:07:26</currentTime>
然后您也可以使用xs:date
作为该元素的类型。