1

ドキュメント内のノードのセットをグループ化し、含まれている値のセットに基づいて一意のリストを取得することに関して、非常に奇妙な問題が発生しています。

次のXMLが与えられます:

<Person>
    <FirstName>John</FirstName>
    <MiddleName>Q</MiddleName>
    <LastName>Person</LastName>
    <Gift>
      <Thing>Moon</Thing>
      <Friend>
          <FirstName>Billy</FirstName>
          <MiddleName>Bob</MiddleName>
          <LastName>Smith</LastName>
      </Friend>
      <Friend>
          <FirstName>Mary</FirstName>
          <MiddleName>Jo</MiddleName>
          <LastName>Smith</LastName>
      </Friend>
    </Gift>
    <Gift>
      <Thing>Pencil</Thing>
    </Gift>
</Person>

「Friend」タグにすべての名前が含まれるパイプ区切りの文字列を生成しようとしています。これが私が使用している現在のスタイルシートです:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:key name="Friends" match="Friend" use="concat(FirstName, MiddleName, LastName)"/>

  <xsl:template match="/Person">
    <xsl:for-each select="Gift/Friend[count(. | key('Friends', concat(FirstName, MiddleName, LastName))[1]) = 1]">
      <xsl:apply-templates select="."/>
      <xsl:if test="position()!=last()">
        <xsl:text>|</xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="Friend">
    <xsl:variable name="name">
      <xsl:value-of select="FirstName"/><xsl:text> </xsl:text>
      <xsl:value-of select="MiddleName"/><xsl:text> </xsl:text>
      <xsl:value-of select="LastName"/><xsl:text> </xsl:text>
    </xsl:variable>
    <xsl:value-of select="normalize-space($name)"/>
  </xsl:template>

</xsl:stylesheet>

私が抱えている問題は、出力で最後の友達が省略されていることです。結果は次のとおりです。

Billy Bob Smith|

面白いことに、最後の「Gift」要素を削除すると、探している出力が生成されます。

Billy Bob Smith|Mary Jo Smith

参考までに、変換の実行に使用されるJavaコードは次のとおりです。

package testing;

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class test
{
  public static void main( String[] args )
  {
    try
    {     
      StreamSource xsl = new StreamSource( "xslt/person.xslt" );
      StreamSource xml = new StreamSource( "xslt/person.xml" );
      Transformer txfm = TransformerFactory.newInstance().newTransformer(xsl);
      if ( txfm != null )
      {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        txfm.transform( xml, new StreamResult(bytes) );
        System.out.println( bytes.toString() );
      }      

    }
    catch ( Exception e )
    {
      e.printStackTrace();
    }
  }
}

あなたが提供できるどんな援助も歓迎されるでしょう。

4

1 に答える 1

0

Saxon 6.5でテストされた変換は完全に機能しており、目的の結果が得られます。

Billy Bob Smith|Mary Jo Smith

これは、JavaXSLTAPIに関連する問題である可能性があります。APIが、たとえばのようなXSLT1.0機能を完全にサポートしていない可能性がありますxsl:key。さらにテストを行い、キーをまったく使用しないようにすることができます。

たとえば、このテンプレートはキーを使用せずに同じタスクを実行します。

    <xsl:template match="/Person">
        <xsl:for-each select="Gift/Friend[not(
            concat(FirstName,MiddleName,LastName)
            =
            preceding::Friend[concat(FirstName, MiddleName, LastName)]
            )]">
      <xsl:apply-templates select="."/>
      <xsl:if test="position()!=last()">
        <xsl:text>|</xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
于 2011-06-15T20:27:35.377 に答える