我正在根据类型对元素列表进行排序,如我的架构中所定义。我知道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's,所以用文字说出来:只有attr1
和attr2
可以进入bar
,只有attr3
}和attr4
可以进入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>
再次感谢您的帮助!
所以我忘记了一个关于我的数据文件的小改动。除了布局之外,其他所有内容都应该是相同的,它是这样嵌套的:
<?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>
我在这里要说明的是,群组内是子类别,我需要匹配这些子类别中的所有内容。
再次感谢!你真是个救星!
我想出了理想的结果。我更改了说
的行<xsl:copy-of select="*[local-name()=document($schema-name)/*/*
到
<xsl:copy-of select="*/*[local-name()=document($schema-name)/*/*
这给了我额外的一点我需要的东西。
答案 0 :(得分:3)
架构(“schema.xs”):
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.whatever.com/schema">
<element name="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>
</element>
</schema>
输入:
<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>
样式表:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:sch="http://www.whatever.com/schema">
<xsl:param name="schema-name" select="'schema.xs'"/>
<xsl:variable name="input" select="/"/>
<xsl:template match="/">
<xsl:apply-templates select="document($schema-name)/node()"/>
</xsl:template>
<xsl:template match="xs:element[xs:complexType]">
<xsl:element name="{@name}" namespace="http://www.whatever.com/schema">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="xs:element[not(xs:complexType)]">
<xsl:element name="{@name}" namespace="http://www.whatever.com/schema">
<xsl:value-of select="$input/*/sch:*[name()=current()/@name or
substring-after(name(),':')=current()/@name]"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
结果:
<?xml version="1.0" encoding="UTF-16"?>
<fooOut xmlns="http://www.whatever.com/schema">
<bar>
<attr1>val1</attr1>
<attr2>val2</attr2>
</bar>
<stuff>
<attr3>val3</attr3>
<attr4>val4</attr4>
</stuff>
</fooOut>
注意:这是一个XSLT 1.0解决方案,但我认为使用XSLT 2.0可以做得更好.-另外,如果模式更合适(元素定义和类型定义)这个方法可以使用键。尽管更复杂,但另一种方法(输入驱动而非模式驱动)也可以完成,但我已经没时间了。
修改:现在,假设这些架构
schemaA.xsd
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.whatever.com/schema">
<include schemaLocation="schemaB.xsd"/>
<element name="fooOut" type="fooOut"/>
<complexType name="fooOut">
<element name="anotherGroup" type="anotherGroup" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
<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>
</schema>
schemaB.xsd
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.whatever.com/schema">
<include schemaLocation="schemaC.xsd"/>
<complexType name="barListType">
<group ref="barGroup" maxOccurs="unbounded" />
</complexType>
<complexType name="stuffListType">
<group ref="stuffGroup" maxOccurs="unbounded" />
</complexType>
</schema>
schemaC.xsd
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.whatever.com/schema">
<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>
</schema>
此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" />
<xsl:param name="schema-name" select="'schemaA.xsd'" />
<xsl:variable name="input" select="/*/*/*" />
<xsl:variable name="root" select="document($schema-name)/*/xs:element[not(..//xs:element/@ref = @name)]" />
<xsl:variable name="uri" select="$root/../@targetNamespace" />
<xsl:template match="/" name="root">
<xsl:param name="schema" select="$root/../*"/>
<xsl:choose>
<xsl:when test="$schema[self::xs:include]">
<xsl:call-template name="root">
<xsl:with-param name="schema" select="$schema[not(self::xs:include)]|document($schema[self::xs:include]/@schemaLocation)/*/*"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="$root">
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="input" select="$input"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="xs:element">
<xsl:param name="schema"/>
<xsl:param name="input"/>
<xsl:variable name="complex" select="xs:complexType|
$schema[self::xs:complexType][@name=current()/@type]"/>
<xsl:element name="{@name|@ref}" namespace="{$uri}">
<xsl:choose>
<xsl:when test="$complex">
<xsl:apply-templates select="$complex">
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="input" select="$input"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$input[local-name()=current()/@name and
namespace-uri()=$uri]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
<xsl:template match="xs:group[@ref]">
<xsl:param name="schema"/>
<xsl:param name="input"/>
<xsl:apply-templates select="$schema[self::xs:group][@name=current()/@ref]">
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="input" select="$input"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="xs:element[@name='name']" priority="1">
<xsl:element name="{@name}" namespace="{$uri}">foobar</xsl:element>
</xsl:template>
<xsl:template match="xs:element[@maxOccurs='unbounded']">
<xsl:param name="schema"/>
<xsl:param name="input"/>
<xsl:variable name="current" select="."/>
<xsl:for-each select="$input">
<xsl:element name="{$current/@name}" namespace="{$uri}">
<xsl:apply-templates select="$schema[self::xs:complexType][@name=$current/@type]">
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="input" select="./*"/>
</xsl:apply-templates>
</xsl:element>
</xsl:for-each>
</xsl:template>
<xsl:template match="*">
<xsl:param name="schema"/>
<xsl:param name="input"/>
<xsl:apply-templates>
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="input" select="$input"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
结果:
<fooOut xmlns="http://www.whatever.com/schema">
<anotherGroup>
<name>foobar</name>
<bar>
<attr1>val1</attr1>
<attr2>val2</attr2>
</bar>
<stuff>
<attr3>val3</attr3>
<attr4>val4</attr4>
</stuff>
</anotherGroup>
<anotherGroup>
<name>foobar</name>
<bar>
<attr1>val5</attr1>
<attr2>val6</attr2>
</bar>
<stuff>
<attr3>val7</attr3>
<attr4>val8</attr4>
</stuff>
</anotherGroup>
</fooOut>
注意:这样可行,但您的第二个问题(或问题)显示没有一般案例样式表。为什么?因为使用XSLT,您必须将输入(具有众所周知的模式)绑定到输出(也具有众所周知的模式)。所以这个特定的样式表可以完成这项工作:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sch="http://www.whatever.com/schema">
<xsl:output method="xml" encoding="UTF-8" />
<xsl:param name="schema-name" select="'schemaC.xsd'" />
<xsl:template match="sch:foo">
<sch:fooOut>
<xsl:apply-templates/>
</sch:fooOut>
</xsl:template>
<xsl:template match="sch:myGroup">
<sch:anotherGroup>
<sch:name>foobar</sch:name>
<sch:bar>
<xsl:copy-of select="*[local-name()=document($schema-name)/*/*[@name='barGroup']//@name]" />
</sch:bar>
<sch:stuff>
<xsl:copy-of select="*[local-name()=document($schema-name)/*/*[@name='stuffGroup']//@name]" />
</sch:stuff>
</sch:anotherGroup>
</xsl:template>
</xsl:stylesheet>
结果:
<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>
答案 1 :(得分:0)
不确定你在这里寻找什么。 XSLT将从源文档复制到目标文档但是您告诉它。例如:
<sch:fooOut>
<sch:bar>
<xsl:copy>
<sch1:attr1>
<sch1:attr2>
</xsl:copy>
</sch:bar>
</sch:fooOut>
您在寻找什么样的验证?如果您正在寻找更具动态性的解决方案,最好使用XSLT以外的其他东西。