1

xsl変換を書きたいのですが、「カウンター」の部分で立ち往生しています。これは基本的に私がやりたいことです:

入力ファイル:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <Pallets>
    <Pallet>
       <Line>
         <Product>test</Product>
       </Line>
       <Line>
         <Product>test2</Product>
       </Line>
    </Pallet>
    <Pallet>
      <Line>
        <Product>test_1</Product>
      </Line>
      <Line>
        <Product>test_2</Product>
      </Line>
     </Pallet>
   </Pallets>
</root>

そして、これが私が出力したいものです:

<?xml version="1.0" encoding="utf-8"?>
<Result>
  <Pallet>
    <ID>2</ID> ==> This is a counter that increments starting from 2
    <ID2>1</ID2> ==> Always "1"
    <Line>
      <ID>3</ID> ==> The counter from above that increments
      <ParentID>2</ParentID> ==> PalletID (ID from above the loop)
      <Name>test</Name>
    </Line>
    <Line>
      <ID>4</ID> ==> The counter from above that increments
      <ParentID>2</ParentID> ==> PalletID
      <Name>test2</Name>
    </Line>
  </Pallet>
  <Pallet>
    <ID>5</ID>  ==> The counter from above that increments
    <ID2>1</ID2> ==> Always "1"
    <Line>
      <ID>6</ID> ==> The counter from above that increments
      <ParentID>5</ParentID> ==> PalletID
      <Name>test_1</Name>
    </Line>
    <Line>
      <ID>7</ID> ==> The counter from above that increments
      <ParentID>5</ParentID> ==> PalletID
      <Name>test_2</Name>
    </Line>
  </Pallet>
</Result>

誰かがこれを手伝ってくれますか?これは私がこれまでに持っているものですが、ご覧のとおり、palletIdのカウンターは正しくありません。2番目のPalletIDは、3ではなくID=5である必要があります。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <Result>
      <xsl:for-each select="root/Pallets/Pallet">
        <xsl:variable name="counter" select="1" />
        <Pallet>
          <xsl:variable name="Parentcounter" select="position() + $counter" />
          <ID>
            <xsl:value-of select="$Parentcounter"/>
          </ID>
          <ID2>1</ID2>
          <xsl:for-each select="Line">
            <Line>
              <ID>
                <xsl:value-of select="$Parentcounter + position()"/>
              </ID>
              <ParentID>
                <xsl:value-of select="$Parentcounter"/>
              </ParentID>
              <Name>
                <xsl:value-of select="Product"/>
              </Name>
            </Line>
          </xsl:for-each>
        </Pallet>
      </xsl:for-each>
    </Result>
  </xsl:template>
</xsl:stylesheet>

前もって感謝します。

4

2 に答える 2

1

Pallet要素のIDは、先行するPallet要素とLine要素の数を数えるだけで取得できます。

<xsl:variable name="id" select="count(preceding::Pallet|preceding::Line) + 2" />
<ID><xsl:value-of select="$id" /></ID>

これをLine 要素に一致するテンプレートでパラメータとして渡した場合、Line要素のIDのようになります ($parentID には親の ID が含まれます)。

<ID><xsl:value-of select="$ParentID + count(preceding-sibling::Line) + 1" /></ID>

したがって、次の XSLT は目的の出力を生成する必要があります。

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

   <xsl:template match="Pallets">
      <Result>
         <xsl:apply-templates select="Pallet" />
      </Result>
   </xsl:template>

   <xsl:template match="Pallet">
      <xsl:variable name="id" select="count(preceding::Pallet|preceding::Line) + 2" />
      <Pallet>
         <ID><xsl:value-of select="$id" /></ID>
         <ID2>1</ID2>
         <xsl:apply-templates select="Line">
            <xsl:with-param name="ParentID" select="$id" />
         </xsl:apply-templates>
      </Pallet>
   </xsl:template>

   <xsl:template match="Line">
      <xsl:param name="ParentID" />
      <Line>
         <ID><xsl:value-of select="$ParentID + count(preceding-sibling::Line) + 1" /></ID>
         <ParentID><xsl:value-of select="$ParentID" /></ParentID>
         <Name><xsl:value-of select="Product" /></Name>
      </Line>
   </xsl:template>
</xsl:stylesheet>

ただし、これは、多数の先行する要素を繰り返しカウントする必要があるため (本質的に同じものを何度もカウントする)、パレットとアイテムの数が多い場合には必ずしも効率的であるとは限りません。もう 1 つの方法は、再帰的なテンプレートを使用して、パレットの ID の現在の合計をパラメーターとして毎回渡すことです。この XSLT も試してください。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:template match="Pallets">
      <Result>
         <xsl:apply-templates select="Pallet[1]"/>
      </Result>
   </xsl:template>

   <xsl:template match="Pallet">
      <xsl:param name="id" select="2"/>
      <Pallet>
         <ID>
            <xsl:value-of select="$id"/>
         </ID>
         <ID2>1</ID2>
         <xsl:apply-templates select="Line[1]">
            <xsl:with-param name="parentID" select="$id"/>
         </xsl:apply-templates>
      </Pallet>
      <xsl:apply-templates select="following-sibling::Pallet[1]">
         <xsl:with-param name="id" select="$id + count(Line) + 1"/>
      </xsl:apply-templates>
   </xsl:template>

   <xsl:template match="Line">
      <xsl:param name="parentID"/>
      <xsl:param name="id" select="$parentID + 1"/>
      <Line>
         <ID>
            <xsl:value-of select="$id"/>
         </ID>
         <ParentID>
            <xsl:value-of select="$parentID"/>
         </ParentID>
         <Name>
            <xsl:value-of select="Product" />
         </Name>
      </Line>

      <xsl:apply-templates select="following-sibling::Line[1]">
         <xsl:with-param name="parentID" select="$parentID"/>
         <xsl:with-param name="id" select="$id + 1"/>
      </xsl:apply-templates>
   </xsl:template>
</xsl:stylesheet>

これも同じ出力を生成します

<Result>
   <Pallet>
      <ID>2</ID>
      <ID2>1</ID2>
      <Line>
         <ID>3</ID>
         <ParentID>2</ParentID>
         <Name>test</Name>
      </Line>
      <Line>
         <ID>4</ID>
         <ParentID>2</ParentID>
         <Name>test2</Name>
      </Line>
   </Pallet>
   <Pallet>
      <ID>5</ID>
      <ID2>1</ID2>
      <Line>
         <ID>6</ID>
         <ParentID>5</ParentID>
         <Name>test_1</Name>
      </Line>
      <Line>
         <ID>7</ID>
         <ParentID>5</ParentID>
         <Name>test_2</Name>
      </Line>
   </Pallet>
</Result>
于 2012-07-03T08:26:24.280 に答える
0

使用する

<xsl:number level="any" count="Pallet|Line"/>

2 から開始するため、これを変数に入れて 1 つ追加する必要があります。

于 2012-07-03T09:03:03.843 に答える