0

以下の構造を持つ XML を変換する必要があります。

<CustomerStatements>
 <CustomerStatement>
  <Name>ABC</Name>
  <ID>1</ID>
  <Amt>10</Amt>
 </CustomerStatement>
 <CustomerStatement>
  <Name>ABC</Name>
  <ID>1</ID>
  <Amt>20</Amt>
 </CustomerStatement>
 <CustomerStatement>
  <Name>XYZ</Name>
  <ID>2</ID>
  <Amt>30</Amt>
 </CustomerStatement>
 <CustomerStatement>
  <Name>XYZ</Name>
  <ID>2</ID>
  <Amt>40</Amt>
 </CustomerStatement>
</CustomerStatements>

<Customers>
 <Customer>
  <Name>ABC</Name>
  <Id>1</Id>
  <Amounts>
   <Amount>10</Amount>
   <Amount>20</Amount>
  </Amounts>
 </Customer>
 <Customer>
  <Name>XYZ</Name>
  <Id>2</Id>
   <Amount>30</Amount>
   <Amount>40</Amount>
 </Customer>
</Customers>

for ループを使用して名前を変数に取り、次のレコードの名前を比較しようとしましたが、うまくいきません。XSLT 疑似コードのサンプルを教えてください。

ありがとう

4

1 に答える 1

1

I. この XSLT 1.0 ソリューションの場合:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key 
    name="kCustByNameId"
    match="CustomerStatement"
    use="concat(Name, '+', ID)" />

  <xsl:template match="/*">
    <Customers>
      <xsl:apply-templates 
        select="CustomerStatement[
          generate-id() = 
          generate-id(key('kCustByNameId', concat(Name, '+', ID))[1])]" />
    </Customers>
  </xsl:template>

  <xsl:template match="CustomerStatement">
    <Customer>
      <xsl:copy-of select="Name|ID" />
      <Amounts>
        <xsl:for-each select="key('kCustByNameId', concat(Name, '+', ID))/Amt">
          <Amount>
            <xsl:apply-templates />
          </Amount>
        </xsl:for-each>
      </Amounts>
    </Customer>
  </xsl:template>
</xsl:stylesheet>

...OP の元の XML に適用されます。

<CustomerStatements>
  <CustomerStatement>
    <Name>ABC</Name>
    <ID>1</ID>
    <Amt>10</Amt>
  </CustomerStatement>
  <CustomerStatement>
    <Name>ABC</Name>
    <ID>1</ID>
    <Amt>20</Amt>
  </CustomerStatement>
  <CustomerStatement>
    <Name>XYZ</Name>
    <ID>2</ID>
    <Amt>30</Amt>
  </CustomerStatement>
  <CustomerStatement>
    <Name>XYZ</Name>
    <ID>2</ID>
    <Amt>40</Amt>
  </CustomerStatement>
</CustomerStatements>

...必要な結果が生成されます。

<?xml version="1.0" encoding="UTF-8"?><Customers>
  <Customer>
    <Name>ABC</Name>
    <ID>1</ID>
    <Amounts>
      <Amount>10</Amount>
      <Amount>20</Amount>
    </Amounts>
  </Customer>
  <Customer>
    <Name>XYZ</Name>
    <ID>2</ID>
    <Amounts>
      <Amount>30</Amount>
      <Amount>40</Amount>
    </Amounts>
  </Customer>
</Customers>

ここでまず注目すべきはMuenchian Groupingです。これは、XSLT 1.0 で問題をグループ化するために一般的に受け入れられている方法です。

Ⅱ.よりコンパクトな XSLT 2.0 ソリューションを次に示します。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output omit-xml-declaration="no" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:template match="/*">
     <Customers>
       <xsl:for-each-group select="CustomerStatement" group-by="ID">
         <Customer>
           <xsl:copy-of select="current-group()[1]/Name|current-group()[1]/ID" />
           <Amounts>
             <xsl:for-each select="current-group()/Amt">
               <Amount>
                 <xsl:apply-templates />
               </Amount>    
             </xsl:for-each>
           </Amounts>
         </Customer>
       </xsl:for-each-group>
     </Customers>
   </xsl:template>      
</xsl:stylesheet>

この場合、XSLT 2.0 でfor-each-group要素が使用されていることに注意してください。これにより、冗長で混乱を招く可能性のある Muenchian Grouping メソッドが不要になります。

于 2012-08-23T15:24:32.183 に答える