2015-07-08 12 views
1

У меня есть документ xml, который включает в себя несколько блоков тестовых определений. С преобразованием xsl я хочу объединить некоторые из этих блоков определения теста вместе, когда они имеют одинаковое имя. После того, как они были объединены, я хочу присвоить номер (Заказ) каждому объединенному определению теста.Подсчет внутри условия if

Пример ввода: (Приказ быть 0 везде преднамеренным, так как я не знаю, на данный момент, сколько тестов все еще будет там после слияния)

<TestDef> 
    <Name>Test1</Name> 
    <Order>0</Order> 
    <Results> 
     <Result Name="Result1"/> 
     <Result Name="Result2"/> 
    </Results> 
</TestDef> 
<TestDef> 
    <Name>Test2</Name> 
    <Order>0</Order> 
    <Results> 
     <Result Name="Result5"/> 
     <Result Name="Result6"/> 
    </Results> 
</TestDef> 
<TestDef> 
    <Name>Test1</Name> 
    <Order>0</Order> 
    <Results> 
     <Result Name="Result3"/> 
     <Result Name="Result4"/> 
    </Results> 
</TestDef> 

Wanted Выход: (Теперь каждый объединенное испытание имеет номер заказа, присвоенный, начиная с 1 и подсчета без пробелов)

<TestDef> 
    <Name>Test1</Name> 
    <Order>1</Order> 
    <Results> 
     <Result Name="Result1"/> 
     <Result Name="Result2"/> 
     <Result Name="Result3"/> 
     <Result Name="Result4"/> 
    </Results> 
</TestDef> 
<TestDef> 
    <Name>Test2</Name> 
    <Order>2</Order> 
    <Results> 
     <Result Name="Result5"/> 
     <Result Name="Result6"/> 
    </Results> 
</TestDef> 

Выходной ток: (Приказ тег Test2 является важным моментом)

<TestDef> 
    <Name>Test1</Name> 
    <Order>1</Order> 
    <Results> 
     <Result Name="Result1"/> 
     <Result Name="Result2"/> 
     <Result Name="Result3"/> 
     <Result Name="Result4"/> 
    </Results> 
</TestDef> 
<TestDef> 
    <Name>Test2</Name> 
    <Order>3</Order> 
    <Results> 
     <Result Name="Result5"/> 
     <Result Name="Result6"/> 
    </Results> 
</TestDef> 

Мой текущий XSLT:

<xsl:key name="unique-tests" match="TestDef" use="Name" /> 
<xsl:strip-space elements="*"/> 

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

<!-- Merge all tests with the same name together and add all results to 
the one new test 
This grouping was done, using the Muenchian Method: 
http://www.jenitennison.com/xslt/grouping/muenchian.html -->  
<xsl:template match="TestDef"> 
    <xsl:if test="generate-id()= generate-id(key('unique-tests', Name))"> 
     <Name> 
      <xsl:value-of select="Name" /> 
     </Name> 
     <Order> 
      <xsl:number /> 
     </Order> 
     <Results> 
      <xsl:for-each select="key('unique-tests', Name)"> 
       <xsl:copy-of select="Results/node()"/> 
      </xsl:for-each> 
     </Results> 
    </xsl:if> 
</xsl:template> 

Проблема:

Группировка работает только отлично, но номер заказа просто не будет работать так, как я этого хочу. Когда я использую <xsl:number/>, как в моем показанном xslt, он будет считать каждый тест с входа, но выводит только некоторые из чисел. Результат для моего примера может быть чем-то вроде Test1 с порядком = 1 и Test2 с порядком = 3.

Когда я добавляю дополнительный вывод <xsl:number/> до условия if, он будет выводить каждое число по порядку, даже если само определение теста не будет присутствовать на выходе.

Теперь я видел другие вопросы, как это одна: xsl counter with and condition Там они рассчитывают с условием, но так как мое собственное состояние не может быть представлено как XPath, я не могу использовать его для атрибута <xsl:number/>

count

Итак, я хочу, чтобы количество тегов Order от 1 до любого количества тестов TestDefs, которое у меня есть, в Выход без пробелов. Как это сделать?

ответ

1

IMHO, было бы предпочтительнее применять шаблоны выборочно - то есть только к тем элементам, которые являются первыми в их группе, - затем используйте функцию position() для их номера.

Чтобы продемонстрировать, мы должны сначала иметь действительный ввод XML с одним корневым элементом и т.д .:

XML

<root> 
    <TestDef> 
     <Name>Test1</Name> 
     <Order>0</Order> 
     <Results> 
      <Result Name="Result1"/> 
      <Result Name="Result2"/> 
     </Results> 
    </TestDef> 
    <TestDef> 
     <Name>Test2</Name> 
     <Order>0</Order> 
     <Results> 
      <Result Name="Result5"/> 
      <Result Name="Result6"/> 
     </Results> 
    </TestDef> 
    <TestDef> 
     <Name>Test1</Name> 
     <Order>0</Order> 
     <Results> 
      <Result Name="Result3"/> 
      <Result Name="Result4"/> 
     </Results> 
    </TestDef> 
</root> 

Тогда вы можете сделать:

XSLT 1.0

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

<xsl:key name="unique-tests" match="TestDef" use="Name" /> 

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

<xsl:template match="/root"> 
    <xsl:copy> 
     <xsl:apply-templates select="TestDef[generate-id() = generate-id(key('unique-tests', Name)[1])]"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="TestDef"> 
    <xsl:copy> 
     <Name><xsl:value-of select="Name" /></Name> 
     <Order><xsl:value-of select="position()" /></Order> 
     <Results> 
      <xsl:for-each select="key('unique-tests', Name)"> 
       <xsl:copy-of select="Results/node()"/> 
      </xsl:for-each> 
     </Results> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

В качестве альтернативы, вы можете продублировать ваше состояние в xsl:number тоже с помощью:

<xsl:number count="TestDef[generate-id() = generate-id(key('unique-tests', Name)[1])]"/> 
+0

Хм, я не знаю, что вы могли бы поставить условие так, как этот в атрибут count. Я попробую, когда вернусь к работе завтра и вернусь к вам! – Bexo

+0

Я пошел с вашим вторым вариантом, так как с первого, группировка вообще не работала. Но с условием в параметре count все работает как ожидалось. Большое спасибо :) – Bexo

+0

«* с первым, группировка вообще не работала». «Это работает для вас: http://xsltransform.net/3NzcBtS? - Недостатком второго варианта является то, что он нарушает принцип DRY. –

Смежные вопросы