8

次の xml フラグメントがあるとします。

<Problems>
  <Problem>
    <File>file1</File>
    <Description>desc1</Description>
  </Problem>
  <Problem>
    <File>file1</File>
    <Description>desc2</Description>
  </Problem>
  <Problem>
    <File>file2</File>
    <Description>desc1</Description>
  </Problem>
</Problems>

次のようなものを作成する必要があります

<html>
  <body>
    <h1>file1</h1>
    <p>des1</p>
    <p>desc2</p>
    <h1>file2</h1>
    <p>des1</p>
  </body>
</html>

のようなキーを使用してみました

<xsl:key name="files" match="Problem" use="File"/>

しかし、次のステップに進む方法、またはそれが正しいアプローチであるかどうかはよくわかりません。

4

3 に答える 3

7

この解決策は、リチャードが提示したものよりも少し単純で効率的であると同時に、より一般的です。

この変換:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--                                            -->
 <xsl:key name="kFileByVal" match="File"
       use="." />
<!--                                            -->
 <xsl:key name="kDescByFile" match="Description"
       use="../File"/>
<!--                                            -->
    <xsl:template match="/*">
     <html>
      <body>
      <xsl:for-each select=
         "*/File[generate-id()
                =
                 generate-id(key('kFileByVal',.)[1])]">
        <h1><xsl:value-of select="."/></h1>
        <xsl:for-each select="key('kDescByFile', .)">
          <p><xsl:value-of select="."/></p>
        </xsl:for-each>
      </xsl:for-each>
      </body>
     </html>
    </xsl:template>
</xsl:stylesheet>

提供された XML ドキュメントに適用された場合:

<Problems>
    <Problem>
        <File>file1</File>
        <Description>desc1</Description>
    </Problem>
    <Problem>
        <File>file1</File>
        <Description>desc2</Description>
    </Problem>
    <Problem>
        <File>file2</File>
        <Description>desc1</Description>
    </Problem>
</Problems>

必要な結果を生成します:

<html>
   <body>
      <h1>file1</h1>
      <p>desc1</p>
      <p>desc2</p>
      <h1>file2</h1>
      <p>desc1</p>
   </body>
</html>

最初の単純一致パターンと<xsl:key>、2 番目の を使用して、指定された値を持つ要素の兄弟である<xsl:key>すべての " " 要素を見つける方法に注意してください。DescriptionFile

プル処理の代わりにより多くのテンプレートを使用することもできましたが<xsl:for-each>、これは非常に単純なケースであり、ソリューションはより短く、よりコンパクトで読みやすいコードから本当に恩恵を受けます。

また、XSLT 2.0 では通常、 <xsl:for-each-group>Muenchian メソッドの代わりに命令を使用することに注意してください。

于 2008-12-30T06:45:01.540 に答える
5

Muencheanメソッドを使用して、これを行う方法を次に示します。Google 'xslt muenchean' で詳しい情報を入手してください。賢い方法があるかもしれませんが、それは他の人に任せます。

1 つの注意点として、'File' などの xml 要素名の先頭に大文字を使用することは避けていますが、それはあなた次第です。

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"/>
    <xsl:key name="files" match="/Problems/Problem/File" use="./text()"/>
    <xsl:template match="/">
        <html>
            <body>
                <xsl:apply-templates select="Problems"/>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="Problems">
        <xsl:for-each select="Problem/File[generate-id(.) = generate-id(key('files', .))]">
            <xsl:sort select="."/>
            <h1>
                <xsl:value-of select="."/>
            </h1>
            <xsl:apply-templates select="../../Problem[File=current()/text()]"/>
        </xsl:for-each>
    </xsl:template>
    <xsl:template match="Problem">
        <p>
            <xsl:value-of select="Description/text()"/>
        </p>
    </xsl:template>
</xsl:stylesheet>

アイデアは、テキスト値を使用して各ファイル要素にキーを設定することです。次に、キー付きの要素と同じ要素である場合にのみ、ファイルの値を表示します。それらが同じかどうかを確認するには、generate-id を使用します。一致する最初の要素を比較する同様のアプローチがあります。どちらが効率的かは一概には言えません。

私のお気に入りの xslt ツールである Marrowsoft Xselerator を使用して、ここでコードをテストしました。私が得た結果は次のとおりです。

<html>
<body>
<h1>file1</h1>
<p>desc1</p>
<p>desc2</p>
<h1>file2</h1>
<p>desc1</p>
</body>
</html>

これは msxml4 を使用しています。

出力をファイル別にソートしました。あなたがそれを望んでいたかどうかはわかりません。

これが役立つことを願っています。

于 2008-12-30T01:12:05.113 に答える
0

このXSLT 1.0ソリューションでもうまくいきます。他のソリューションよりも少し簡潔です!

  <xsl:template match="/">           
    <html><body>
      <xsl:for-each select="//File[not(.=preceding::*)]">
        <h1><xsl:value-of select="." /></h1>
        <xsl:for-each select="//Problem[File=current()]/Description">
          <p><xsl:value-of select="." /></p>
        </xsl:for-each>
      </xsl:for-each>
    </body></html>
  </xsl:template>

結果:

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
    <h1>file1</h1>
    <p>desc1</p>
    <p>desc2</p>
    <h1>file2</h1>
    <p>desc1</p>
  </body>
</html>
于 2013-09-19T04:41:40.947 に答える