如何使用 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()"/>