如何使用 XSLT 根据属性值检索 xml 文档和组节点
How to retrieve an xml document and group nodes based on attribute value using XSLT
所以让我们假设当我开始转换时我的交易主体是完全空的。
我有一个 xml 文件,其中包含如下数据:
<?xml version="1.0" encoding="UTF-8"?>
<codes>
<code sourceCode="10" targetCode="06" area="MAIL"/>
<code sourceCode="11" targetCode="1" area="PROFESSION"/>
<code sourceCode="11" targetCode="11" area="HOME"/>
<code sourceCode="12" targetCode="13" area="HOME"/>
<code sourceCode="12" targetCode="3" area="HOME"/>
<code sourceCode="13" targetCode="10" area="PROFESSION"/>
<code sourceCode="14" targetCode="01" area="WORK"/>
<code sourceCode="14" targetCode="05" area="MAIL"/>
</codes>
我需要这样的结果:
<codes>
<code>
<sourceCode>10</sourceCode>
<areas>
<area>MAIL</area>
</areas>
</code>
<code>
<sourceCode>11</sourceCode>
<areas>
<area>PROFESSION</area>
<area>HOME</area>
</areas>
</code>
<!-- This code has two different targetCodes with the same area
but in the result it should not have the same area twice in the areas list -->
<code>
<sourceCode>12</sourceCode>
<areas>
<area>HOME</area>
</areas>
</code>
<code>
<sourceCode>13</sourceCode>
<areas>
<area>PROFESSION</area>
</areas>
</code>
<code>
<sourceCode>14</sourceCode>
<areas>
<area>WORK</area>
<area>MAIL</area>
</areas>
</code>
</codes>
这里有两个挑战。
第一个是原始文档不是交易的主体,但您必须在 xsl 中检索它。
第二个是实际的转换以及如何通过 sourceCode 属性实现这种分组,同时完全消除 targetCode 属性并且没有重复区域。
在 XSL 文件的开头,这是我检索 XML 文档的方式:
<xsl:variable name="lookupDoc" select="document('../common/lookup/mapping.xml')"/>
编辑:
最后我还想完全过滤掉“MAIL”区域。所以在最后的 xml 中,第一个代码元素将被删除,而最后一个代码元素将只有一个区域(“WORK”)。
使用类似
的模板
<xsl:template match="codes">
<xsl:copy>
<xsl:for-each-group select="code" group-by="@sourceCode">
<xsl:copy>
<sourceCode>
<xsl:value-of select="current-grouping-key()"/>
</sourceCode>
<areas>
<xsl:for-each select="distinct-values(current-group()/@area)">
<area>
<xsl:value-of select="."/>
</area>
</xsl:for-each>
</areas>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
然后通过该模板推送 <xsl:apply-templates select="$lookupDoc/node()"/>
。
所以让我们假设当我开始转换时我的交易主体是完全空的。
我有一个 xml 文件,其中包含如下数据:
<?xml version="1.0" encoding="UTF-8"?>
<codes>
<code sourceCode="10" targetCode="06" area="MAIL"/>
<code sourceCode="11" targetCode="1" area="PROFESSION"/>
<code sourceCode="11" targetCode="11" area="HOME"/>
<code sourceCode="12" targetCode="13" area="HOME"/>
<code sourceCode="12" targetCode="3" area="HOME"/>
<code sourceCode="13" targetCode="10" area="PROFESSION"/>
<code sourceCode="14" targetCode="01" area="WORK"/>
<code sourceCode="14" targetCode="05" area="MAIL"/>
</codes>
我需要这样的结果:
<codes>
<code>
<sourceCode>10</sourceCode>
<areas>
<area>MAIL</area>
</areas>
</code>
<code>
<sourceCode>11</sourceCode>
<areas>
<area>PROFESSION</area>
<area>HOME</area>
</areas>
</code>
<!-- This code has two different targetCodes with the same area
but in the result it should not have the same area twice in the areas list -->
<code>
<sourceCode>12</sourceCode>
<areas>
<area>HOME</area>
</areas>
</code>
<code>
<sourceCode>13</sourceCode>
<areas>
<area>PROFESSION</area>
</areas>
</code>
<code>
<sourceCode>14</sourceCode>
<areas>
<area>WORK</area>
<area>MAIL</area>
</areas>
</code>
</codes>
这里有两个挑战。 第一个是原始文档不是交易的主体,但您必须在 xsl 中检索它。 第二个是实际的转换以及如何通过 sourceCode 属性实现这种分组,同时完全消除 targetCode 属性并且没有重复区域。
在 XSL 文件的开头,这是我检索 XML 文档的方式:
<xsl:variable name="lookupDoc" select="document('../common/lookup/mapping.xml')"/>
编辑: 最后我还想完全过滤掉“MAIL”区域。所以在最后的 xml 中,第一个代码元素将被删除,而最后一个代码元素将只有一个区域(“WORK”)。
使用类似
的模板 <xsl:template match="codes">
<xsl:copy>
<xsl:for-each-group select="code" group-by="@sourceCode">
<xsl:copy>
<sourceCode>
<xsl:value-of select="current-grouping-key()"/>
</sourceCode>
<areas>
<xsl:for-each select="distinct-values(current-group()/@area)">
<area>
<xsl:value-of select="."/>
</area>
</xsl:for-each>
</areas>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
然后通过该模板推送 <xsl:apply-templates select="$lookupDoc/node()"/>
。