我正在根据我的架构中定义的类型对元素列表进行排序。我知道 XSLT 可以针对给定的模式进行验证,但我想做的是在执行之前检查以确保我的操作(在这种情况下为副本)是有效的。
简化代码:
传入数据:
<?xml version="1.0"?>
<sch:foo xmlns:sch="http://www.whatever.com/schema">
<sch:attr1>val1</sch:attr1>
<sch:attr2>val2</sch:attr2>
<sch:attr3>val3</sch:attr3>
<sch:attr4>val4</sch:attr4>
</sch:foo>
所需的传出数据:
<?xml version="1.0"?>
<sch:fooOut xmlns:sch="http://www.whatever.com/schema">
<sch:bar>
<sch:attr1>val1</sch:attr1>
<sch:attr2>val2</sch:attr2>
</sch:bar>
<sch:stuff>
<sch:attr3>val3</sch:attr3>
<sch:attr4>val4</sch:attr4>
</sch:stuff>
</sch:fooOut>
架构文件中的某处:
<complexType name="fooOut">
<sequence>
<!-- ... -->
<element name="bar">
<complexType>
<sequence>
<element name="attr1" type="sch:myBarType" minOccurs="0" maxOccurs="unbounded"/>
<element name="attr2" type="sch:myBarType" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
</element>
<element name="stuff">
<complexType>
<sequence>
<element name="attr3" type="sch:myStuffType" minOccurs="0" maxOccurs="unbounded"/>
<element name="attr4" type="sch:myStuffType" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
(我只是在学习如何使用 .xsd,所以用语言来表达:only attr1
and attr2
can go in bar
, and only attr3
and attr4
can go in stuff
)
基本上,在实际情况下,标签太多,无法手动将它们分开。我想知道是否有办法检查架构中的元素是否适合需要分类的任何类型。如果他们属于一个类别,他们应该只属于那个类别。
感谢所有帮助,谢谢!
编辑
@Alejandro 的代码适用于上述基本伪代码,但我无法在我的文件中实现它,这些文件更复杂。出于这个原因,我添加了一个更复杂的示例:
传入数据
<?xml version="1.0"?>
<sch:foo xmlns:sch="http://www.whatever.com/schema">
<sch:nesting>
<sch:myGroup>
<sch:mustHaveData>asdf</sch:mustHaveData>
<sch:attr1>val1</sch:attr1>
<sch:attr2>val2</sch:attr2>
<sch:attr3>val3</sch:attr3>
<sch:attr4>val4</sch:attr4>
</sch:myGroup>
<sch:myGroup>
<sch:mustHaveData>asdf2</sch:mustHaveData>
<sch:attr1>val5</sch:attr1>
<sch:attr2>val6</sch:attr2>
<sch:attr3>val7</sch:attr3>
<sch:attr4>val8</sch:attr4>
</sch:myGroup>
</sch:nesting>
</sch:foo>
所需的传出数据:
<?xml version="1.0"?>
<sch:fooOut xmlns:sch="http://www.whatever.com/schema">
<sch:anotherGroup>
<sch:name>foobar</sch:name>
<sch:bar>
<sch:attr1>val1</sch:attr1>
<sch:attr2>val2</sch:attr2>
</sch:bar>
<sch:stuff>
<sch:attr3>val3</sch:attr3>
<sch:attr4>val4</sch:attr4>
</sch:stuff>
</sch:anotherGroup>
<sch:anotherGroup>
<sch:name>foobar</sch:name>
<sch:bar>
<sch:attr1>val5</sch:attr1>
<sch:attr2>val6</sch:attr2>
</sch:bar>
<sch:stuff>
<sch:attr3>val7</sch:attr3>
<sch:attr4>val8</sch:attr4>
</sch:stuff>
</sch:anotherGroup>
</sch:fooOut>
架构文件中的某处:(并且比上次更准确)
<complexType name="anotherGroup">
<sequence>
<element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<element name="bar" type="barListType" minOccurs="0" maxOccurs="1" />
<element name="stuff" type="stuffListType" minOccurs="0" maxOccurs="1" />
</sequence>
</complexType>
<!-- in another .xsd -->
<complexType name="barListType">
<group ref="barGroup" maxOccurs="unbounded" />
</complexType>
<complexType name="stuffListType">
<group ref="stuffGroup" maxOccurs="unbounded" />
</complexType>
<!-- in yet another .xsd -->
<group name="barGroup">
<choice>
<element name="attr1" type="blah1" minOccurs="0" maxOccurs="1" />
<element name="attr2" type="blah2" minOccurs="0" maxOccurs="1" />
<!-- etc -->
</choice>
</group>
<group name ="stuffGroup">
<choice>
<element name="attr3" type="blah3" minOccurs="0" maxOccurs="1" />
<element name="attr4" type="blah4" minOccurs="0" maxOccurs="1" />
<!-- etc -->
</choice>
</group>
最后,我的 xsl 文件
<xsl:output method="xml" encoding="UTF-8" />
<xsl:param name="schema-name" select="'myXsd.xsd'" />
<xsl:template match="/">
<xsl:apply-templates select="document($schema-name)/xs:complexType[@*]" />
<xsl:apply-templates select="sch:nesting"/>
</xsl:template>
<xsl:template match="sch:nesting/xs:element[xs:complexType]">
<xsl:element name="{@name}" namespace="http://www.whatever.com/schema">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="sch:nesting/xs:element[not(xs:complexType)]">
<xsl:element name="{@name}" namespace="http://www.whatever.com/schema">
<xsl:value-of select="/*/sch:*[name()=current()/@name or
substring-after(name(),':')=current()/@name]"/>
</xsl:element>
</xsl:template>
<xsl:template match="sch:nesting">
<xsl:element name="anotherGroup">
<xsl:element name="name">
<!-- Whatever -->
</xsl:element>
<xsl:apply-templates /> <!-- I want to drop the data here, but this is definitely wrong -->
</xsl:element>
</xsl:template>
</xsl:stylesheet>
再次感谢您的帮助!
编辑 2
因此,我忘记对我的数据文件进行一项小的更改。除了布局,其他一切都应该是相同的,它是这样嵌套的:
<?xml version="1.0"?>
<sch:foo xmlns:sch="http://www.whatever.com/schema">
<sch:nesting>
<sch:myGroup>
<inner1>
<sch:mustHaveData>asdf</sch:mustHaveData>
<sch:attr1>val1</sch:attr1>
</inner1>
<inner2>
<sch:attr2>val2</sch:attr2>
<sch:attr3>val3</sch:attr3>
<sch:attr4>val4</sch:attr4>
</inner2>
</sch:myGroup>
<sch:myGroup>
<inner1>
<sch:mustHaveData>asdf2</sch:mustHaveData>
<sch:attr1>val5</sch:attr1>
</inner1>
<inner2>
<sch:attr2>val6</sch:attr2>
<sch:attr3>val7</sch:attr3>
<sch:attr4>val8</sch:attr4>
</inner2>
</sch:myGroup>
</sch:nesting>
</sch:foo>
我在这里试图说明的是,组中有子类别,我需要匹配这些子类别中的所有内容。
亚历杭德罗,为了让这个值得你花时间(因为你一直是一个了不起的帮助),你应该把你的回应放在一个新的答案中,当我尝试它并让它发挥作用时,我会投票并接受这个答案。
再次感谢!你真的是救命恩人!
编辑 3
我想出了想要的结果。我改变了说
<xsl:copy-of select="*[local-name()=document($schema-name)/*/*
到
<xsl:copy-of select="*/*[local-name()=document($schema-name)/*/*
这给了我所需的额外部分。