1

非常にトリッキーな XSLT の質問があります。次の入力があるとします。

<OtherCharges>        
<LineId>
    <Id>P</Id>
</LineId>
<Items>
    <Item1>1</Item1>
    <Item2>2</Item2>
    <Item3>3</Item3>  
</Items>    
<LineId>
    <Id>P</Id>
</LineId>
<Items>
    <Item1>4</Item1>
</Items>
<LineId>
    <Id>P</Id>
</LineId>
<Items>
    <Item1>5</Item1>
    <Item2>6</Item2>    
</Items>
</OtherCharges>

出力として、私はこれを持ちたいと思います:

<OtherCharges>
  <LineId>P</LineId>
  <OtherChargesValues>
    <value>1</value>
    <value>2</value>
    <value>3</value>
  </OtherChargesValues>
</OtherCharges>
<OtherCharges> 
  <LineId>P</LineId>
  <OtherChargesValues>
    <value>4</value>
  </OtherChargesValues>
</OtherCharges>
<OtherCharges> 
  <LineId>P</LineId>
  <OtherChargesValues>
    <value>5</value>
    <value>6</value>
  </OtherChargesValues>
</OtherCharges>

行数に制限はありませんが、各行には最大 3 つの項目があります。私は次のコードを試しました:

<xsl:for-each select="/OtherCharges/LineId">
<Id>
    <xsl:value-of select="Id"/>
<Id>
<xsl:variable name="ChargeLine" select="."/>
<xsl:for-each select="following-sibling::Items[preceding-sibling::LineId[1] = $ChargeLine]">    
    <xsl:if test="name(.)='Items'">
        <xsl:if test="Item1">
            <value>
                <xsl:value-of select="Item1"/>
            </value>
        </xsl:if>  
        <xsl:if test="Item2">
            <value>
                <xsl:value-of select="Item2"/>
            </value>
        </xsl:if> 
        <xsl:if test="Item3">
            <value>
                <xsl:value-of select="Item3"/>
            </value>
        </xsl:if>
    </xsl:if>
</xsl:for-each>

ID が異なっていても問題はありませんが、問題は ID 値が同じ場合です (例のように)。誰でもこれで私を助けることができますか?

ありがとう。

4

3 に答える 3

1

starts-with()役立つかもしれません...

XML入力

<OtherCharges>        
    <LineId>
        <Id>P</Id>
    </LineId>
    <Items>
        <Item1>1</Item1>
        <Item2>2</Item2>
        <Item3>3</Item3>  
    </Items>    
    <LineId>
        <Id>P</Id>
    </LineId>
    <Items>
        <Item1>4</Item1>
    </Items>
    <LineId>
        <Id>P</Id>
    </LineId>
    <Items>
        <Item1>5</Item1>
        <Item2>6</Item2>    
    </Items>
</OtherCharges>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="Id">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Items/*[starts-with(name(),'Item')]">
        <value>
            <xsl:apply-templates select="@*|node()"/>
        </value>
    </xsl:template>

</xsl:stylesheet>

XML出力(整形式ではありません)

<Id>P</Id>
<value>1</value>
<value>2</value>
<value>3</value>
<Id>P</Id>
<value>4</value>
<Id>P</Id>
<value>5</value>
<value>6</value>
于 2012-08-30T19:30:17.497 に答える
1

一般に、value-of の使用を避け、apply-template について学ぶと、これは非常に簡単な XSLT の質問になります。ちなみに、単一のルート ラッパー要素がないため、出力は整形式の XML ではありません。

<xsl:strip-space elements="OtherCharges" />

<xsl:template match="OtherCharges">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="OtherCharges/LineId">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="OtherCharges/Items">
  <xsl:apply-templates/>
</xsl:template>

<!--* now the real work *-->
<xsl:template match="OtherCharges/LineId/Id">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="OtherCharges/Items/*">
  <value><xsl:apply-templates/></value>
</xsl:template>
于 2012-08-30T19:22:22.337 に答える
1

この変換:

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

 <xsl:key name="kFollowing" match="*[not(self::LineId)]"
  use="generate-id(preceding-sibling::LineId[1])"/>

 <xsl:template match="LineId">
  <OtherCharges>
     <LineId><xsl:value-of select="."/></LineId>
     <OtherChargesValues>
       <xsl:apply-templates mode="inGroup"
            select="key('kFollowing', generate-id())"/>
     </OtherChargesValues>
  </OtherCharges>
 </xsl:template>

 <xsl:template match="Items/*" mode="inGroup">
  <value><xsl:value-of select="."/></value>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

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

<OtherCharges>
    <LineId>
        <Id>P</Id>
    </LineId>
    <Items>
        <Item1>1</Item1>
        <Item2>2</Item2>
        <Item3>3</Item3>
    </Items>
    <LineId>
        <Id>P</Id>
    </LineId>
    <Items>
        <Item1>4</Item1>
    </Items>
    <LineId>
        <Id>P</Id>
    </LineId>
    <Items>
        <Item1>5</Item1>
        <Item2>6</Item2>
    </Items>
</OtherCharges>

必要な正しい結果が生成されます。

<OtherCharges>
   <LineId>P</LineId>
   <OtherChargesValues>
      <value>1</value>
      <value>2</value>
      <value>3</value>
   </OtherChargesValues>
</OtherCharges>
<OtherCharges>
   <LineId>P</LineId>
   <OtherChargesValues>
      <value>4</value>
   </OtherChargesValues>
</OtherCharges>
<OtherCharges>
   <LineId>P</LineId>
   <OtherChargesValues>
      <value>5</value>
      <value>6</value>
   </OtherChargesValues>
</OtherCharges>
于 2012-08-31T03:13:02.130 に答える