2014-11-28 6 views
0

У меня проблема с группировкой нескольких ключей на основе критериев.Как слить несколько ключей с разными условиями

У меня 2 записей в формате XML. Документ 1 и Документ 2

Целью является создание таблицы с двумя разделами. То же самое, изменения.

Элементы, имеющие одинаковые элементы rec_no, part_no, ext_qty, которые находятся в обоих документах, должны поступать в подраздел Same. Элемент, который присутствует в обоих документах, но с изменением в rec_no, part_no, ext_qty должен находиться под пунктом изменения.

Теперь для этого я создал различные ключи на этих условиях. Теперь моя проблема заключается в том, как сгруппировать ключи для получения результатов.

Вот таблица с моими комментариями.

--------------------------------------------------------- 
Section RecNo Desc Doc-1 Qty Doc-2 Qty Total 
--------------------------------------------------------- 
Same 111  Desc1 1   1   100 

--------------------------------------------------------- 
Same Total          100 
--------------------------------------------------------- 
Change 222  Desc2 2   3   500 
Change 333  Desc3 3   3   600 
Change 444  Desc4 6   4   600 
--------------------------------------------------------- 
Change Total         1300 
--------------------------------------------------------- 
Grand Total          1400 
--------------------------------------------------------- 

Мой XML является:

<Logia> 
    <DocHeader> 
     <Document> 
      <Downto> 
       <part_no>111</part_no> 
       <rec_no>aaa</rec_no> 
       <desc>Desc1</desc> 
       <ext_qty>1</ext_qty> 
       <mat_cost>100.00</mat_cost> 
      </Downto> 
      <Downto> 
       <part_no>222</part_no> 
       <rec_no>bbb</rec_no> 
       <desc>Desc2</desc> 
       <ext_qty>2</ext_qty> 
       <mat_cost>100.00</mat_cost> 
      </Downto> 
      <Downto> 
       <part_no>333</part_no> 
       <rec_no>ccc</rec_no> 
       <desc>Desc3</desc> 
       <ext_qty>3</ext_qty> 
       <mat_cost>100.00</mat_cost> 
      </Downto> 
      <Downto> 
       <part_no>444</part_no> 
       <rec_no>ddd</rec_no> 
       <desc>Desc4</desc> 
       <ext_qty>6</ext_qty> 
       <mat_cost>100.00</mat_cost> 
      </Downto> 

     </Document> 
     <Document> 
      <Downto> 
       <part_no>111</part_no> 
       <rec_no>aaa</rec_no> 
       <desc>Desc1</desc> 
       <ext_qty>1</ext_qty> 
       <mat_cost>100.00</mat_cost> 
      </Downto> 
      <Downto> 
       <part_no>222</part_no> 
       <rec_no>bbb</rec_no> 
       <desc>Desc3</desc> 
       <ext_qty>3</ext_qty> 
       <mat_cost>100.00</mat_cost> 
      </Downto> 
      <Downto> 
       <part_no>333</part_no> 
       <rec_no>bbb</rec_no> 
       <desc>Desc3</desc> 
       <ext_qty>3</ext_qty> 
       <mat_cost>100.00</mat_cost> 
      </Downto> 
      <Downto> 
       <part_no>444</part_no> 
       <rec_no>ddd</rec_no> 
       <desc>Desc4</desc> 
       <ext_qty>4</ext_qty> 
       <mat_cost>400.00</mat_cost> 
      </Downto>       
     </Document> 
    </DocHeader> 
</Logia> 

и мой XSLT является

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

<xsl:key name="MAT1PARTKEY" match="Document[1]/Downto" use="part_no" /> 
<xsl:key name="MAT2PARTKEY" match="Document[2]/Downto" use="part_no" /> 
<xsl:key name="MAT1RECKEY" match="Document[1]/Downto" use="rec_no" /> 
<xsl:key name="MAT2RECKEY" match="Document[2]/Downto" use="rec_no" /> 
<xsl:key name="MAT1QTYKEY" match="Document[1]/Downto" use="ext_qty" /> 
<xsl:key name="MAT2QTYKEY" match="Document[2]/Downto" use="ext_qty" /> 
<xsl:key name="MAT1COSTKEY" match="Document[1]/Downto" use="mat_cost" /> 
<xsl:key name="MAT2COSTKEY" match="Document[2]/Downto" use="mat_cost" /> 

<xsl:key name="MATERIALBYPARTNO" match="Document/Downto" use="part_no" /> 

<xsl:template match="/Logia/DocHeader"> 
    <table border="1"> 
     <!-- header --> 
     <tr> 
      <th>Section</th> 
      <th>PartNo</th> 
      <th>RecNo</th> 
      <th>Desc</th> 
      <th>Doc-1 Qty</th> 
      <th>Doc-2 Qty</th> 
      <th> Total</th> 
     </tr> 
     <!-- same --> 
     <xsl:variable name="same" select="Document[1]/Downto[key('MAT2RECKEY', part_no]" /> 
     <xsl:apply-templates select="$same"> 
      <xsl:with-param name="section">Same</xsl:with-param> 
     </xsl:apply-templates> 
     <xsl:variable name="same-total" select="sum($same/mat_cost)" />  
     <tr> 
      <td colspan="6">Same Total</td> 
      <th><xsl:value-of select="$same-total"/></th> 
     </tr>  
     <!-- change --> 
     <xsl:variable name="change" select="Document[1]/Downto[not(key('MAT2RECKEY', rec_no))]" /> 
     <xsl:apply-templates select="$change"> 
      <xsl:with-param name="section">Change</xsl:with-param> 
     </xsl:apply-templates> 
     <xsl:variable name="change-total" select="sum($change/mat_cost)" />  
     <tr> 
      <td colspan="6">Change Total</td> 
      <th><xsl:value-of select="$change-total"/></th> 
     </tr> 

     <!-- grand total --> 
     <tr> 
      <th colspan="6">Grand Total</th> 
      <th><xsl:value-of select="$same-total + $add-total + $delete-total"/></th> 
     </tr> 
    </table> 
</xsl:template> 

<xsl:template match="Downto"> 
    <xsl:param name="section"/> 
    <xsl:if test="generate-id() = generate-id(key('MATERIALBYPARTNO', part_no)[1])"> 
     <tr> 
      <td><xsl:value-of select="$section"/></td> 
      <td><xsl:value-of select="part_no"/></td> 
      <td><xsl:value-of select="rec_no"/></td>    
      <td><xsl:value-of select="desc"/></td> 
      <td><xsl:value-of select="sum(key('MAT1PARTKEY', part_no)/ext_qty)"/></td> 
      <td><xsl:value-of select="sum(key('MAT2PARTKEY', part_no)/ext_qty)"/></td> 
      <td><xsl:value-of select="sum(key('MATERIALBYPARTNO', part_no)/mat_cost)"/></td> 
     </tr> 

    </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

Любая помощь приветствуется

ответ

0

а. Ключи по количеству и стоимости бесполезны.

b. Вы можете построить ключ любой сложности. В вас так:

<xsl:key name="downtoByKeyFields" match="Downto" use="concat(rec_no, '||', part_no, '||', ext_qty)"/> 

и когда вы вызываете этот ключ, вы должны сделать то же самое:

key('downtoByKeyFields', concat(rec_no, '||', part_no, '||', ext_qty)) 

Этот ключ будет возвращать все Downto поля, имеющие заданную комбинацию rec_no, part_no, значения ext_qty ,

p.s. Это должно работать, если ни одно из этих значений не содержит || :)


Основная идея:

<xsl:key name="MATERIAL2BYKEY" match="Document[2]/Downto" use="concat(rec_no, '||', part_no, '||', ext_qty)" /> 

... 

<xsl:variable name="same" select="Document[1]/Downto[key('MATERIAL2BYKEY', concat(rec_no, '||', part_no, '||', ext_qty))]" /> 

... 

<xsl:variable name="change" select="Document[1]/Downto[not(key('MATERIAL2BYKEY', concat(rec_no, '||', part_no, '||', ext_qty)))]" /> 

Это довольно просто: элементы, которые имеют такой же rec_no, part_no, ext_qty с точки зрения ключей является ключом, который соответствует всем элементам с той же rec_no, part_no, ext_qty. Нам нужно указать выражение, которое сообщит xslt transformer, что два элемента имеют такие же rec_no, part_no, ext_qty - concat (rec_no, 'some separator', part_no, 'some separator', ext_qty), например.

+0

Спасибо Рудольф. Я пробовал это, но я получаю записи с изменением количества в одних и тех же записях. || символ обозначает "или" условие право. Должен ли я использовать + для «и» условия – user2822294

+0

Нет, || это просто разделитель строк, вы можете использовать любые символы, не ожидаемые в rec_no, part_no и ext_qty. –

+0

Отличный рудольф. Теперь я понял. Огромное спасибо. Ценить это – user2822294

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