0

xslテンプレートを使用して、xmlドキュメントを元の要素階層を持つ別のxmlドキュメントに変換する方法を知りたいです。また、新しく生成されたXMLの要素にいくつかの属性を追加したいと思います。

私の元のXMLファイルは次のようになります。

<shop> 
  <product>
    <cookie ID="001">
    <price>2</price>
    </cookie>
  </product>

  <product>
    <bread ID="002">
    <price>5</price>
    </bread>
  </product>

  <product>
    <milk ID="003">
    <price>2</price>
    </milk>
  </product>
</shop>

これを次のXMLに変換したいと思います。

<newXML> 
  <newElement>
    <newElement ID="001">
    <newElement price="2"/>
    </newElement>
  </newElement>

  <newElement>
    <newElement ID="002">
    <newElement price="5"/>
    </newElement>
  </newElement>

  <newElement>
    <newElement ID="003">
    <newElement price="2"/>
    </newElement>
  </newElement>
</newXML>

これを行うための良い方法は何でしょうか?これは、テンプレートで再帰を使用して実行できますか、それともより良い方法がありますか?私は次のロジックを使用しようとしています:

  1. 要素を作成するテンプレートを作成する
  2. 現在の要素IDが存在する場合はそれを読み取り、newElementに配置します
  3. 現在の要素に子がある場合は、このテンプレートをその要素に適用します(ある種の再帰)

多くの試みにもかかわらず、私はこの仕事をすることができませんでした。あなたの助けをいただければ幸いです!

4

2 に答える 2

2

これを行うには、XSLTで非常に一般的なデザインパターンであるXSLTIdentityTransformに基づいて構築します。まず、要素をコピーしてそのまま出力するテンプレートがあります]

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

次に、要素に一致するテンプレートを追加し、コードを追加して名前を変更するか、必要に応じて属性を追加します。たとえば、ルート要素の名前を変更するには、次のテンプレートを追加します。

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

ここでも特定の要素名を使用する必要はありません。ID属性を持つ要素の名前を同じ名前に変更したい場合は、次のようにすることができます

<xsl:template match="product/*[@ID]">
   <newElement>
      <xsl:apply-templates select="@*|node()"/>
   </newElement>
</xsl:template>

また、price要素の場合、要素のテキストコンテンツに基づいて属性を作成する場合は、次のようなテンプレートを追加できます。

<xsl:template match="price">
   <newElement price="{.}" />
</xsl:template>

(これは、ここで属性を作成するために属性値テンプレートを使用することに注意してください。これは通常、xsl:attributeを使用するよりも優先されます)

初心者のためにこのXMLを試してください:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

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

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

   <xsl:template match="product/*[@ID]">
      <newElement>
         <xsl:apply-templates select="@*|node()"/>
      </newElement>
   </xsl:template>

   <xsl:template match="price">
      <newElement price="{.}" />
   </xsl:template>

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

これにより、次のように出力されます。

<newXML>
   <newElement>
      <newElement ID="001">
         <newElement price="2"/>
      </newElement>
   </newElement>
   <newElement>
      <newElement ID="002">
         <newElement price="5"/>
      </newElement>
   </newElement>
   <newElement>
      <newElement ID="003">
         <newElement price="2"/>
      </newElement>
   </newElement>
</newXML>
于 2013-02-17T13:25:37.057 に答える
0

ドキュメントを変換したいだけのように聞こえるので、XSLTの代わりにXQueryを試してみませんか?それははるかに簡単です。

作成したいxmlを記述し、{..}そこに入力ファイルから何かを挿入for $variable in //xpathして、xpath式と一致する入力ファイルの部分でそれを繰り返す場合。

したがって、これにより目的のxmlファイルが作成されます。

<newXML>{
  for $prod in /shop/product/* return
    <newElement>
      <newElement>{
        $prod/@ID,
        for $value in $prod/* return 
          <newElement price="{$value}"/>
      }</newElement>
    </newElement>
}</newXML> 
于 2013-02-17T14:14:15.993 に答える