我有一个如下所示的XML:
<root>
<name>
<elements T="BI" S="1">1</elements>
<elements T="BI" S="2">2</elements>
<elements T="BI" S="3">3</elements>
</name>
<name>
<elements T="BM" S="1">10</elements>
<elements T="BM" S="2">20</elements>
<elements T="BM" S="3">30</elements>
</name>
<name>
<elements T="XX" S="1">001</elements>
<elements T="XX" S="2">002</elements>
<elements T="XX" S="3">003</elements>
</name>
<name>
<elements T="XX" S="1">005</elements>
<elements T="XX" S="2">007</elements>
<elements T="XX" S="3">009</elements>
</name> </root>
我试图使用以下XSLT转换将此XML转换为另一个XML:
<xsl:for-each select="root">
<name_code_1>
<xsl:for-each select="name">
<xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
<xsl:if test="@T = 'XX' and @S = '1'">
<xsl:value-of select="substring(./text(),1,1000)"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</name_code_1>
<name_code_2>
<xsl:for-each select="name">
<xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
<xsl:if test="@T = 'XX' and @S = '2'">
<xsl:value-of select="substring(./text(),1,1000)"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</name_code_2>
<name_code_3>
<xsl:for-each select="name">
<xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
<xsl:if test="@T = 'XX' and @S = '3'">
<xsl:value-of select="substring(./text(),1,1000)"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</name_code_3>
<name_code_4>
<xsl:for-each select="name">
<xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
<xsl:if test="@T = 'XX' and @S = '1'">
<xsl:value-of select="substring(./text(),1,1000)"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</name_code_4>
<name_code_5>
<xsl:for-each select="name">
<xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
<xsl:if test="@T = 'XX' and @S = '2'">
<xsl:value-of select="substring(./text(),1,1000)"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</name_code_5>
<name_code_6>
<xsl:for-each select="name">
<xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
<xsl:if test="@T = 'XX' and @S = '3'">
<xsl:value-of select="substring(./text(),1,1000)"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</name_code_6> </xsl:for-each>
我想要展平名称标签,其中T-attribute =&#34; XX&#34;并且基于S-attribute =&#34; 1&#34;或&#34; 2&#34;等等......将这些元素填充到6个不同的XML标记中,如下所示。 以上逻辑不起作用。有人可以通过提供一些如何解决这个问题的建议来帮助我。
以下是所需的最终输出:
<some_tag>
<name_code_1>001</name_code_1>
<name_code_2>002</name_code_2>
<name_code_3>003</name_code_3>
<name_code_4>005</name_code_4>
<name_code_5>007</name_code_5>
<name_code_6>009</name_code_6> </some_tag>
由于 Qubiter
答案 0 :(得分:2)
一种方法是使用position()
函数从elements
个节点的子集中获取节点索引:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text()" /> <!-- remove superfluous text() nodes -->
<xsl:template match="/root"> <!-- main match and creation of <some_tag> element -->
<some_tag>
<xsl:apply-templates select="name/elements[@T='XX']" /> <!-- create subset of nodes with attribute @T='XX' -->
</some_tag>
</xsl:template>
<xsl:template match="elements"> <!-- match elements from subset list -->
<xsl:element name="{concat('name_code_',position())}"> <!-- concat position to node-name -->
<xsl:value-of select="." /> <!-- copy value -->
</xsl:element>
</xsl:template>
</xsl:stylesheet>
输出为:
<some_tag>
<name_code_1>001</name_code_1>
<name_code_2>002</name_code_2>
<name_code_3>003</name_code_3>
<name_code_4>005</name_code_4>
<name_code_5>007</name_code_5>
<name_code_6>009</name_code_6>
</some_tag>
答案 1 :(得分:1)
此方法使用for-each-group,如果您使用的是XSLT 2.0,这是最好的方法。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<xsl:for-each-group select="name/elements" group-adjacent="if(@T='XX') then 'element' else 'cc'">
<xsl:choose>
<xsl:when test="current-grouping-key() = 'element'">
<some_tag>
<xsl:for-each select="current-group()">
<xsl:variable name="ss" select="position()"/>
<xsl:element name="{concat('name_code_', $ss)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</some_tag>
</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
以下是上述XSLT生成的输出。
<?xml version="1.0" encoding="UTF-8"?>
<some_tag>
<name_code_1>001</name_code_1>
<name_code_2>002</name_code_2>
<name_code_3>003</name_code_3>
<name_code_4>005</name_code_4>
<name_code_5>007</name_code_5>
<name_code_6>009</name_code_6>
</some_tag>