3

ソース XML は次のとおりです。

<customers>
    <firstname1>Sean</firstname1>
    <lastname1>Killer</lastname1>
    <sex1>M</sex1>
    <firstname2>Frank</firstname2>
    <lastname2>Woods</lastname2>
    <sex2>M</sex2>
    <firstname3>Jennifer</firstname3>
    <lastname3>Lee</lastname3>
    <sex3>F</sex3>
</customers>

どうすればこれに変換できますか?

<MyCustomers>
    <Customer>
        <Name> Sean Killer</Name>
        <Sex>M</Sex>
    </Customer>
    <Customer>
        <Name> Frank Woods</Name>
        <Sex>M</Sex>
    </Customer>
    <Customer>
        <Name>Jennifer Lee</Name>
        <Sex>F</Sex>
    </Customer>
</MyCustomers>
4

3 に答える 3

4

コメントによると:

要素が結果順序にない場合はどうなりますか?

この場合 (XSLT 1.0 を想定) を使用translate()して要素の ID を取得し、 を使用して構築された正しい名前で対応する要素を検索できますconcat()following-sibling::軸を../(の略) に変更してparent::、最終的に現在の の前の要素も確実にキャッチできるようにしfirstnameます。

<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:template match="customers">
        <MyCustomers>
            <xsl:apply-templates select="*[starts-with(name(),'firstname')]"/>
        </MyCustomers>
    </xsl:template>

    <xsl:template match="*[starts-with(name(),'firstname')]">
        <xsl:variable name="id" select="translate(name(),'firstname','')"/>

        <Customer>
            <Name><xsl:value-of select="concat(.,' ',
                    ../*[name()=concat('lastname',$id)])"/></Name>
            <Sex><xsl:value-of select="../*[name()=concat('sex',$id)]"/></Sex>
        </Customer>
    </xsl:template>

</xsl:stylesheet>

時代遅れの答え

質問に示されているように固定された入力ドキュメント構造を想定すると、適切に機能する XSLT 1.0 変換は次のようになります。

<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:template match="customers">
        <MyCustomers>
            <xsl:apply-templates select="*[starts-with(name(),'firstname')]"/>
        </MyCustomers>
    </xsl:template>

    <xsl:template match="*[starts-with(name(),'firstname')]">
        <Customer>
            <Name><xsl:value-of select="concat(.,' ',
                    following-sibling::*[1]
                    [starts-with(name(),'lastname')])"/></Name>
            <Sex><xsl:value-of select="following-sibling::*[2]
                    [starts-with(name(),'sex')]"/></Sex>
        </Customer>
    </xsl:template>

</xsl:stylesheet>

少し説明

starts-with()XML入力のタグの名前が悲しいため、XPath 1.0関数が必要です。軸を使用してfollowing-sibling::、名前が で始まる任意の要素の必要な次の兄弟タグを取得できますfirstname

于 2011-07-11T20:34:17.937 に答える
0

この変換により、最上位の要素の子が任意の方法でシャッフルされた場合でも、目的の結果が生成されます

<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:variable name="vNumCustomers"
      select="count(/*/*) div 3"/>

 <xsl:template match="/*">
     <MyCustomers>
       <xsl:for-each select=
           "*[not(position() > $vNumCustomers)]">
         <xsl:variable name="vNum" select="position()"/>

         <Customer>
          <Name>
            <xsl:value-of select=
             "concat(/*/*[name()=concat('firstname',$vNum)],
                     ' ',
                     /*/*[name()=concat('lastname',$vNum)]
                     )
             "/>
          </Name>
          <Sex>
            <xsl:value-of select=
             "/*/*[name()=concat('sex',$vNum)]
             "/>
          </Sex>
         </Customer>
       </xsl:for-each>
     </MyCustomers>
 </xsl:template>
</xsl:stylesheet>

このXMLドキュメントに適用した場合(提供されたものの任意の再シャッフル):

<customers>
    <sex1>M</sex1>
    <lastname2>Woods</lastname2>
    <lastname1>Killer</lastname1>
    <sex2>M</sex2>
    <firstname3>Jennifer</firstname3>
    <firstname2>Frank</firstname2>
    <lastname3>Lee</lastname3>
    <firstname1>Sean</firstname1>
    <sex3>F</sex3>
</customers>

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

<MyCustomers>
   <Customer>
      <Name>Sean Killer</Name>
      <Sex>M</Sex>
   </Customer>
   <Customer>
      <Name>Frank Woods</Name>
      <Sex>M</Sex>
   </Customer>
   <Customer>
      <Name>Jennifer Lee</Name>
      <Sex>F</Sex>
   </Customer>
</MyCustomers>

説明

  1. データが提示されている顧客の数を計算します。変数$vNumCustomersはこのデータを保持します。

  2. 各customer{i}(i = 1 to )に対して、対応する要素$vNumCustomersを作成します。<Customer{i}>再帰の使用を避けるために、ここではPiezメソッドを使用します。

于 2011-07-12T13:02:15.887 に答える
0

これは、順序が正しくなくても、探している出力が得られる XSLT 2.0 スタイルシートです。また、「firstname」要素名でソートします。

サンプル XML 入力 (異なる順序を示すために混合):

<customers>
  <lastname1>Killer</lastname1>
  <sex3>F</sex3>
  <firstname2>Frank</firstname2>
  <firstname1>Sean</firstname1>
  <lastname2>Woods</lastname2>
  <sex2>M</sex2>
  <firstname3>Jennifer</firstname3>
  <sex1>M</sex1>
  <lastname3>Lee</lastname3>
</customers>

XSLT 2.0 スタイルシート (Saxon-HE 9.3 でテスト済み):

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

  <xsl:template match="node()|@*">
    <xsl:choose>
      <xsl:when test="name()[starts-with(.,'firstname')]">
        <xsl:variable name="suffix" select="substring(name(),10)"></xsl:variable>
        <xsl:message><xsl:value-of select="$suffix"/></xsl:message>
        <customer>
          <Name>
            <xsl:value-of select="concat(.,' ',/customers/*[starts-with(name(),'lastname')][ends-with(name(),$suffix)])"/>  
          </Name>
          <Sex>
            <xsl:value-of select="/customers/*[starts-with(name(),'sex')][ends-with(name(),$suffix)]"/>
          </Sex>
        </customer>
      </xsl:when>
      <xsl:when test="name()='customers'">
        <MyCustomers>
          <xsl:apply-templates>
            <xsl:sort select="name()[starts-with(.,'firstname')]"></xsl:sort>
          </xsl:apply-templates>
        </MyCustomers>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="node()|@*"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

出力:

<MyCustomers>
   <customer>
      <Name>Sean Killer</Name>
      <Sex>M</Sex>
   </customer>
   <customer>
      <Name>Frank Woods</Name>
      <Sex>M</Sex>
   </customer>
   <customer>
      <Name>Jennifer Lee</Name>
      <Sex>F</Sex>
   </customer>
</MyCustomers>
于 2011-07-11T21:09:21.977 に答える