【问题标题】:Converting input XML using XSLT to other XML使用 XSLT 将输入 XML 转换为其他 XML
【发布时间】:2012-07-02 00:42:18
【问题描述】:

我是初学者,想学习 XSLT。我遇到了使用 XSLT 将输入 XML 文件转换为另一个 XML 文件的问题。

我的输入 XML 文件:

<album>
<album_num>hi.hello</album_num>
<album_name>Cocktail</album_name>
</album>
<album>
<album_num>hey.hello</album_num>
<album_name>Mocktail</album_name>
</album>
<album>
<album_num>hey.mello</album_num>
<album_name>Monkeytail</album_name>
</album>
<album>
<album_num>hey.yellow</album_num>
<album_name>Donkeytail</album_name>
</album>
<album>
<album_num>swallow</album_num>
<album_name>abc</album_name>
</album>

我想得到这样的输出 XML 文件:

<album>
<album_num>
<hi>
<hello>cocktail</hello>
</hi>
</album_num>
<album_num>
<hey>
<hello>MockTail</hello>
<mello>Monkeytail</mello>
<yellow>Donkeytail</yellow>
</hey>
</album_num>
<album_num>
<swallow>abc</swallow>
</album_num>
</album>

我通过创建变量尝试了第一部分,但在将相似元素合并到一个元素下时遇到了问题。任何代码都可以帮助我学习。

我的代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<album>
<xsl:variable name="fstval" select='substring-before(//album/album_num,".")'/>
<xsl:variable name="secval" select='substring-after(//album/album_num,".")'/>
<xsl:variable name="valtoappend" select='//album/album_name'/>
<album_num>
<xsl:element name="{$fstval}">
<xsl:element name="{$secval}">
<xsl:value-of select="$valtoappend"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</album_num>
</album>
</xsl:template>
</xsl:stylesheet>

【问题讨论】:

    标签: xml xslt xml-parsing


    【解决方案1】:

    这种转变

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:key name="kAlbumByChildName" match="album" use="name(album_num/*[1])"/>
    
     <xsl:template match="/">
      <xsl:variable name="vrtfPass1">
        <xsl:apply-templates/>
      </xsl:variable>
    
      <xsl:apply-templates mode="pass2" select=
      "ext:node-set($vrtfPass1)/*
               [generate-id()
               =
                generate-id(key('kAlbumByChildName', name(album_num/*[1]))[1])
               ]
      "/>
     </xsl:template>
    
     <xsl:template match="album">
      <album>
       <album_num>
           <xsl:element name="{substring-before(album_num, '.')}">
             <xsl:element name="{substring-after(album_num, '.')}">
               <xsl:value-of select="album_name"/>
             </xsl:element>
           </xsl:element>
       </album_num>
      </album>
     </xsl:template>
    
     <xsl:template match="album" mode="pass2">
      <album>
       <album_num>
            <xsl:apply-templates select="*/*[1]" mode="pass2"/>
        </album_num>
      </album>
     </xsl:template>
    
     <xsl:template match="album_num/*" mode="pass2">
      <xsl:copy>
       <xsl:copy-of select="key('kAlbumByChildName', name())/*/*/*"/>
      </xsl:copy>
     </xsl:template>
    </xsl:stylesheet>
    

    应用于以下文档时(提供的 XML 片段包装在单个顶部元素中以使其成为格式良好的 XML 文档):

    <t>
        <album>
            <album_num>hi.hello</album_num>
            <album_name>Cocktail</album_name>
        </album>
        <album>
            <album_num>hey.hello</album_num>
            <album_name>Mocktail</album_name>
        </album>
        <album>
            <album_num>hey.mello</album_num>
            <album_name>Monkeytail</album_name>
        </album>
        <album>
            <album_num>hey.yellow</album_num>
            <album_name>Donkeytail</album_name>
        </album>
    </t>
    

    产生想要的正确结果:

    <album>
       <album_num>
          <hi>
             <hello>Cocktail</hello>
          </hi>
       </album_num>
    </album>
    <album>
       <album_num>
          <hey>
             <hello>Mocktail</hello>
             <mello>Monkeytail</mello>
             <yellow>Donkeytail</yellow>
          </hey>
       </album_num>
    </album>
    

    解释

    这是一个两遍转换。第一遍的结果是

    <album>
       <album_num>
          <hi>
             <hello>Cocktail</hello>
          </hi>
       </album_num>
    </album>
    
    <album>
       <album_num>
          <hey>
             <hello>Mocktail</hello>
          </hey>
       </album_num>
    </album>
    
    <album>
       <album_num>
          <hey>
             <mello>Monkeytail</mello>
          </hey>
       </album_num>
    </album>
    
    <album>
       <album_num>
          <hey>
             <yellow>Donkeytail</yellow>
          </hey>
       </album_num>
    </album>
    

    第二遍是标准的 Muenchian 分组。

    更新

    在提出这个问题并收到正确答案两天后,OP 更改了源 XML 文档并希望得到结果。

    稍作修改的转换

    <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
         xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
         <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
         <xsl:key name="kAlbumByChildName" match="album" use="name(album_num/*[1])"/>
    
         <xsl:template match="/">
          <xsl:variable name="vrtfPass1">
            <xsl:apply-templates/>
          </xsl:variable>
    
          <xsl:apply-templates mode="pass2" select=
          "ext:node-set($vrtfPass1)/*
                   [generate-id()
                   =
                    generate-id(key('kAlbumByChildName', name(album_num/*[1]))[1])
                   or
                    not(album_num/*)
                   ]
          "/>
    
         </xsl:template>
    
         <xsl:template match="album[contains(album_num, '.')]">
          <album>
           <album_num>
               <xsl:element name="{substring-before(album_num, '.')}">
                 <xsl:element name="{substring-after(album_num, '.')}">
                   <xsl:value-of select="album_name"/>
                 </xsl:element>
               </xsl:element>
           </album_num>
          </album>
         </xsl:template>
    
         <xsl:template match="album">
          <album>
           <album_num>
                 <xsl:element name="{album_num}">
                   <xsl:value-of select="album_name"/>
                 </xsl:element>
           </album_num>
          </album>
         </xsl:template>
    
         <xsl:template match="album" mode="pass2">
          <album>
           <album_num>
                <xsl:apply-templates select="*/*[1]" mode="pass2"/>
            </album_num>
          </album>
         </xsl:template>
    
         <xsl:template match="album_num/*" mode="pass2">
          <xsl:copy>
           <xsl:copy-of select="self::*[not(*)]/text()|key('kAlbumByChildName', name())/*/*/*"/>
          </xsl:copy>
         </xsl:template>
    </xsl:stylesheet>
    

    应用于新版本的 XML 文档时

    <t>
        <album>
            <album_num>hi.hello</album_num>
            <album_name>Cocktail</album_name>
        </album>
        <album>
            <album_num>hey.hello</album_num>
            <album_name>Mocktail</album_name>
        </album>
        <album>
            <album_num>hey.mello</album_num>
            <album_name>Monkeytail</album_name>
        </album>
        <album>
            <album_num>hey.yellow</album_num>
            <album_name>Donkeytail</album_name>
        </album>
        <album>
            <album_num>swallow</album_num>
            <album_name>abc</album_name>
        </album>
    </t>
    

    产生新的想要的结果

    <album>
       <album_num>
          <hi>
             <hello>Cocktail</hello>
          </hi>
       </album_num>
    </album>
    <album>
       <album_num>
          <hey>
             <hello>Mocktail</hello>
             <mello>Monkeytail</mello>
             <yellow>Donkeytail</yellow>
          </hey>
       </album_num>
    </album>
    <album>
       <album_num>
          <swallow>abc</swallow>
       </album_num>
    </album>
    

    【讨论】:

    • 谢谢迪米特。我很高兴感谢您对像我这样的初学者的帮助。
    • @Ramana:很高兴我的回答对您有所帮助。请您接受它(通过勾选答案旁边的复选标记)吗?
    • @Ramana:请参阅此答案的更新——它解决了您修改的问题。你不认为你必须接受这个答案吗?
    • 我很抱歉,我不知道使用这个 stackoverflow。我删除了重复的问题。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 2021-01-18
    • 2019-12-05
    • 2019-04-11
    • 1970-01-01
    • 2017-12-25
    相关资源
    最近更新 更多