1

私は初心者で、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>

変数を作成して最初の部分を試しましたが、1 つの要素の下に同様の要素をマージする際に問題がありました。どのコードも学習に役立ちます。

私のコード:

<?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>
4

1 に答える 1

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>

説明:

これは 2 パス変換です。最初のパスの結果は次のとおりです。

<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>

2 番目のパスは、標準の Muenchian グループ化です。

更新

この質問をして正解を受け取ってから 2 日後、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>
于 2012-07-02T01:25:36.007 に答える