2012-07-03 2 views
1

Я хочу написать преобразование xsl, но застрял на части «счетчик». Это в основном то, что я хочу сделать:Преобразование контура счетчика 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 неверен. Второй PalletID должен иметь ID = 5 вместо 3:

<?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> 

Заранее спасибо.

ответ

1

Вы можете получить ID из более элемента поддонов путем простого подсчета количества предшествующих Поддона и Line элементов

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

Если вы прошли это в качестве параметра в соответствии шаблона Строка элементов, то IDСтрока Элемент будет выглядеть следующим образом (где $ parentID содержит идентификатор родительского)

<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> 

Однако, это не обязательно будет что эффективным для увеличения количества поддонов и изделий, потому что он пришлось бы повторно подсчитывать большее количество предшествующих элементов (по сути, считая одно и то же снова и снова). Другой способ - использовать рекурсивные шаблоны, передавая в общем количестве идентификатора для паллета в качестве параметра каждый раз. Попробуйте 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> 
+0

Спасибо. Я использовал решение с шаблонами :) –

0

Используйте

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

Поскольку вы начинаете с 2, вы должны поместить его в переменную и добавить один.