使用 XSL 将原始输入 XML 转换为结构化 XML



我尝试将XSL与"for-each"一起使用我需要根据类别和类型对值进行分组。

有什么帮助吗?

输入原始 xml:

<?xml version = '1.0' encoding = 'UTF-8'?>
<ROWSET>
<ROW>
<ID>12345</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>1</VALUE>
<LABEL>ISO1</LABEL>
</ROW>
<ROW>
<ID>12345</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>2</VALUE>
<LABEL>ISO2</LABEL>
</ROW>
<ROW>
<ID>12345</ID>
<TYPE>TYP1</TYPE>
<SUBTYPE>SUBTYP2</SUBTYP>
<CATEGORY>A1</CATEGORY>
<VALUE>3</VALUE>
<LABEL>ISO3</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>1</VALUE>
<LABEL>ISO1</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>1</VALUE>
<LABEL>ISO1</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>2</VALUE>
<LABEL>ISO2</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP2</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>3</VALUE>
<LABEL>ISO3</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP2</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>2</VALUE>
<LABEL>ISO2</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP2</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>3</VALUE>
<LABEL>ISO1</LABEL>
</ROW>
</ROWSET>

预期成果:我需要根据类别和类型对值进行分组(见下文)

<?xml version = '1.0' encoding = 'UTF-8'?>
<ROWSET>
<ROW>
<ID>12345</ID>
    <TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
    <GRP1>
    <VALUE>1</VALUE>
    <LABEL>ISO1</LABEL>
    <VALUE>2</VALUE>
    <LABEL>ISO2</LABEL>
    <VALUE>3</VALUE>
    <LABEL>ISO3</LABEL>
    </GRP1>         
</ROW>
<ROW>
<ID>67890</ID>
  <TYP>
    <TYPE>TYP1</TYPE>
    <TYPE>TYP2</TYPE>
  </TYP>
<CATEGORY>A1</CATEGORY>
    <GRP1>
    <VALUE>1</VALUE>
    <LABEL>ISO1</LABEL>
    <VALUE>2</VALUE>
    <LABEL>ISO2</LABEL>
    <VALUE>3</VALUE>
    <LABEL>ISO3</LABEL>
    </GRP1>         

使用的 XSL:它需要一些更正。(感谢@Parfait的代码)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="categkey" match="ROW" use="CATEGORY" />
<xsl:template match="ROWSET">
<xsl:copy>
  <xsl:for-each select="ROW[generate-id()= generate-id(key('categkey', CATEGORY)[1])]">
    <xsl:copy>
      <xsl:copy-of select="ID"/>
      <xsl:copy-of select="TYPE"/>
      <xsl:copy-of select="CATEGORY"/>
      <GRP1>
        <xsl:for-each select="key('categkey', CATEGORY)">            
            <xsl:copy-of select="VALUE"/>
            <xsl:copy-of select="LABEL"/>            
        </xsl:for-each>
      </GRP1>
    </xsl:copy>
  </xsl:for-each>
    </xsl:copy>
 </xsl:template>
</xsl:transform>

谢谢!卡西克

对于 XSLT 1.0 中的分组,请考虑 Muenchian 方法,该方法根据键索引文档,并可以使用该键运行各种操作:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="categkey" match="ROW" use="CATEGORY" />
  <xsl:template match="ROWSET">
    <xsl:copy>
      <xsl:for-each select="ROW[generate-id()= generate-id(key('categkey', CATEGORY)[1])]">
        <xsl:copy>
          <xsl:copy-of select="ID"/>
          <xsl:copy-of select="TYPE"/>
          <xsl:copy-of select="CATEGORY"/>
          <GRP1>
            <xsl:for-each select="key('categkey', CATEGORY)">            
                <xsl:copy-of select="VALUE"/>
                <xsl:copy-of select="LABEL"/>            
            </xsl:for-each>
          </GRP1>
        </xsl:copy>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
</xsl:transform>

更新

借用@Tim C之前的答案(首先编辑您的帖子的XSLT大师),对于多个键,例如On ID及其兄弟姐妹,请考虑以下内容:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="idkey" match="ROW" use="ID" />
<xsl:key name="typekey" match="ROW" use="concat(ID, TYPE)"/>
<xsl:key name="categkey" match="ROW" use="concat(ID, CATEGORY)" />
<xsl:key name="valuekey" match="ROW" use="concat(ID, VALUE)" />
<xsl:key name="labelkey" match="ROW" use="concat(ID, LABEL)" />
  <xsl:template match="ROWSET">
    <xsl:copy>
      <xsl:for-each select="ROW[generate-id()= generate-id(key('idkey', ID)[1])]">
        <xsl:copy>
          <xsl:copy-of select="ID"/>
          <TYP>            
            <xsl:for-each select="key('idkey', ID)[generate-id()= generate-id(key('typekey', concat(ID, TYPE))[1])]">            
                <xsl:copy-of select="TYPE"/>                                    
            </xsl:for-each>
          </TYP>
          <xsl:copy-of select="CATEGORY"/>
          <GRP1>
            <xsl:for-each select="key('idkey', ID)[generate-id()= generate-id(key('valuekey', concat(ID, VALUE))[1])]">
              <xsl:copy-of select="VALUE"/>          
              <xsl:copy-of select="LABEL"/>
            </xsl:for-each>
          </GRP1>
        </xsl:copy>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
</xsl:transform>

最新更新