用于从非线性 XML 结构中提取元素的 XSLT
XSLT for extracting elements from a non linear XML structure
我有一个 XML 结构,其中 XML 模式是 irregular/not 格式的。结构看起来像这样-
<Host>
<element1>type0</element1>
<element2>Fruits</element2>
....
<elementn>Price0</elementn>
<Menu>
<NodeA>
<element1>type1</element1>
<element2>Fruits</element2>
....
<elementn>Price1</elementn>
<Menu>
<NodeB>
<element1>type2</element1>
<element2>Fruits</element2>
....
<elementn>Price2</elementn>
<Menu>
<NodeC>
<element1>type3</element1>
<element2>Fruits</element2>
....
<elementn>Price3</elementn>
<Menu>
<NodeD>
<Element1>type4</element1>
<Element2>Vegetables</Element2>
....
<Elementn>Price4</elementn>
</NodeD>
</Menu>
</NodeC>
</Menu>
</NodeB>
</Menu>
</NodeA>
<NodeE>
<element1>type5</element1>
<element2>Fruits</element2>
....
<elementn>Price5</elementn>
<Menu>
<NodeF>
<element1>type6</element1>
<element2>Vegetables</element2>
....
<elementn>Price6</elementn>
</NodeF>
</Menu>
</NodeE>
</Menu>
</Host>
现在我的预期XML如下-
a) 如果所有节点中 <element2>
== fruits,我需要 XML 模式如下。我可以在 host -
下包含或排除以下 n 个元素
`<element1>type0</element>
<element2>Fruits</element2>
....
<elementn>Price0</elementn>`
. 预期结果 -
<Host>
<NodeA>
<element1>type1</element1>
<element2>Fruits</element2>
....
<elementn>Price1</elementn>
</NodeA>
<NodeB>
<element1>type2</element1>
<element2>Fruits</element2>
....
<elementn>Price2</elementn>
</NodeB>
<NodeC>
<element1>type3</element1>
<element2>Fruits</element2>
....
<elementn>Price3</elementn>
</NodeC>
<NodeE>
<element1>type5</element1>
<element2>Fruits</element2>
....
<elementn>Price5</elementn>
</NodeE>
</Host>
b) 如果所有节点中 <element2>
== vegetables,我需要 XML schema 如下
注意:<element2>
== Vegetables 始终位于架构中的最后一个节点
<Host>
<NodeD>
<element1>type4</element1>
<element2>Vegetables</element2>
....
<elementn>Price4</elementn>
</NodeD>
<NodeF>
<element1>type6</element1>
<element2>Vegetables</element2>
....
<elementn>Price6</elementn>
</NodeF>
</Host>
任何通过 XSLT 获取上述 XML 格式的帮助都是很大的帮助。
如果您想要 2 个单独的文档,实际上不需要 2 个 XSLT。您可以使用一个 XSLT 但带有一个参数
<xsl:param name="element2" select="'Fruits'" />
(此处'Fruits'
只是默认值,如果调用应用程序未指定该参数)。
您将从选择 element2
等于参数的节点开始(请注意 XML 并且 XSLT 区分大小写,因此 element2
与Element2
在您的 XML 中,但我认为这是您在 XML 中的错字。
<xsl:apply-templates select="//*[element2=$element2]"/>
您还需要一个模板来确保匹配节点时,它不会复制子节点...
<xsl:template match="*[element2]">
<xsl:copy>
<xsl:apply-templates select="*[not(*)]" />
</xsl:copy>
</xsl:template>
其他节点将由标识模板处理。
试试这个 XSLT...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:param name="element2" select="'Fruits'" />
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="//*[element2=$element2]" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[element2]" mode="copy">
<xsl:copy>
<xsl:apply-templates select="*[not(*)]" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
请注意,如果您使用的是 XSLT 2.0,则可以在一次调用中创建多个文档,使用 xsl:for-each-group
获取不同的组,并使用 xsl:result-document
为每个组创建一个文件。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/*">
<xsl:for-each-group select="//*[element2]" group-by="element2">
<xsl:result-document href="{current-grouping-key()}.xml" method="xml">
<Host>
<xsl:apply-templates select="current-group()" mode="copy" />
</Host>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="*[element2]" mode="copy">
<xsl:copy>
<xsl:apply-templates select="*[not(*)]" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我有一个 XML 结构,其中 XML 模式是 irregular/not 格式的。结构看起来像这样-
<Host>
<element1>type0</element1>
<element2>Fruits</element2>
....
<elementn>Price0</elementn>
<Menu>
<NodeA>
<element1>type1</element1>
<element2>Fruits</element2>
....
<elementn>Price1</elementn>
<Menu>
<NodeB>
<element1>type2</element1>
<element2>Fruits</element2>
....
<elementn>Price2</elementn>
<Menu>
<NodeC>
<element1>type3</element1>
<element2>Fruits</element2>
....
<elementn>Price3</elementn>
<Menu>
<NodeD>
<Element1>type4</element1>
<Element2>Vegetables</Element2>
....
<Elementn>Price4</elementn>
</NodeD>
</Menu>
</NodeC>
</Menu>
</NodeB>
</Menu>
</NodeA>
<NodeE>
<element1>type5</element1>
<element2>Fruits</element2>
....
<elementn>Price5</elementn>
<Menu>
<NodeF>
<element1>type6</element1>
<element2>Vegetables</element2>
....
<elementn>Price6</elementn>
</NodeF>
</Menu>
</NodeE>
</Menu>
</Host>
现在我的预期XML如下-
a) 如果所有节点中 <element2>
== fruits,我需要 XML 模式如下。我可以在 host -
`<element1>type0</element>
<element2>Fruits</element2>
....
<elementn>Price0</elementn>`
. 预期结果 -
<Host>
<NodeA>
<element1>type1</element1>
<element2>Fruits</element2>
....
<elementn>Price1</elementn>
</NodeA>
<NodeB>
<element1>type2</element1>
<element2>Fruits</element2>
....
<elementn>Price2</elementn>
</NodeB>
<NodeC>
<element1>type3</element1>
<element2>Fruits</element2>
....
<elementn>Price3</elementn>
</NodeC>
<NodeE>
<element1>type5</element1>
<element2>Fruits</element2>
....
<elementn>Price5</elementn>
</NodeE>
</Host>
b) 如果所有节点中 <element2>
== vegetables,我需要 XML schema 如下
注意:<element2>
== Vegetables 始终位于架构中的最后一个节点
<Host>
<NodeD>
<element1>type4</element1>
<element2>Vegetables</element2>
....
<elementn>Price4</elementn>
</NodeD>
<NodeF>
<element1>type6</element1>
<element2>Vegetables</element2>
....
<elementn>Price6</elementn>
</NodeF>
</Host>
任何通过 XSLT 获取上述 XML 格式的帮助都是很大的帮助。
如果您想要 2 个单独的文档,实际上不需要 2 个 XSLT。您可以使用一个 XSLT 但带有一个参数
<xsl:param name="element2" select="'Fruits'" />
(此处'Fruits'
只是默认值,如果调用应用程序未指定该参数)。
您将从选择 element2
等于参数的节点开始(请注意 XML 并且 XSLT 区分大小写,因此 element2
与Element2
在您的 XML 中,但我认为这是您在 XML 中的错字。
<xsl:apply-templates select="//*[element2=$element2]"/>
您还需要一个模板来确保匹配节点时,它不会复制子节点...
<xsl:template match="*[element2]">
<xsl:copy>
<xsl:apply-templates select="*[not(*)]" />
</xsl:copy>
</xsl:template>
其他节点将由标识模板处理。
试试这个 XSLT...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:param name="element2" select="'Fruits'" />
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="//*[element2=$element2]" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[element2]" mode="copy">
<xsl:copy>
<xsl:apply-templates select="*[not(*)]" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
请注意,如果您使用的是 XSLT 2.0,则可以在一次调用中创建多个文档,使用 xsl:for-each-group
获取不同的组,并使用 xsl:result-document
为每个组创建一个文件。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/*">
<xsl:for-each-group select="//*[element2]" group-by="element2">
<xsl:result-document href="{current-grouping-key()}.xml" method="xml">
<Host>
<xsl:apply-templates select="current-group()" mode="copy" />
</Host>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="*[element2]" mode="copy">
<xsl:copy>
<xsl:apply-templates select="*[not(*)]" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>