【问题标题】:Advanced XSLT Transformation for XML to XML Conversion用于 XML 到 XML 转换的高级 XSLT 转换
【发布时间】:2018-04-24 22:45:30
【问题描述】:

我有一个如下所示的 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="XX" 并基于 S-attribute="1" 或 "2" 等的名称标签...将这些元素填充到 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>

谢谢 量子比特

【问题讨论】:

    标签: xml xslt data-transform


    【解决方案1】:

    一种方法是使用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>
    

    【讨论】:

      【解决方案2】:

      此方法使用 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>
      

      【讨论】:

        猜你喜欢
        • 2020-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-02
        • 2019-10-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多