2013-09-23 36 views
2

我最近問了一個關於如何忽略多個元素的問題,並且得到了關於使用'在前'和Muenchian方法的一些很好的回答。但是我想知道是否有可能通過索引xml文件在多個文件中執行此操作。XSLT忽略多個文件中的重複元素

INDEX.XML

<?xml-stylesheet type="text/xsl" href="merge2.xsl"?> 
<list> 
    <entry name="File1.xml" /> 
    <entry name="File2.xml" /> 
</list> 

XML文件的示例

<Main> 
    <Records> 
     <Record> 
      <Description>A</Description> 
     </Record> 
     <Record> 
      <Description>A</Description> 
     </Record> 
     <Record> 
      <Description>B</Description> 
     </Record> 
     <Record> 
      <Description>C</Description> 
     </Record> 
    </Records> 
    <Records> 
     <Record> 
      <Description>B</Description> 
     </Record> 
     <Record> 
      <Description>A</Description> 
     </Record> 
     <Record> 
      <Description>C</Description> 
     </Record> 
     <Record> 
      <Description>C</Description> 
     </Record> 
    </Records> 
</Main> 

Merge2.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:key name="Record-by-Description" match="Record" use="Description"/> 

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

    <xsl:template match="Main"> 
    <table> 
     <tr> 
     <th>Type</th> 
     <th>Count</th> 
     </tr> 
     <xsl:apply-templates select="Records"/> 
    </table> 
    </xsl:template> 

    <xsl:template match="Records"> 
    <xsl:apply-templates select="Record[generate-id() = generate-id(key('Record-by-Description', Description)[1])]" mode="group"/> 
    </xsl:template> 

    <xsl:template match="Record" mode="group"> 
    <tr> 
     <td> 
     <xsl:value-of select="Description"/> 
     </td> 
     <td> 
     <xsl:value-of select="count(key('Record-by-Description', Description))"/> 
     </td> 
    </tr> 
    </xsl:template> 

</xsl:stylesheet> 

能正常工作的一個文件,並給我產生的理想結果一張桌子,只顯示唯一的項目並添加計數。但是,當我通過index.xml查看多個文件時,我一直無法產生所需的結果。

我試過使用一個單獨的模板來定位index.xml,並將'Main'模板應用於不同的XML文件,並嘗試使用for-each來遍歷不同的文件。

在引入Muenchian方法之前,我使用for-each和'preceding'來檢查重複節點,但是'之前'似乎只能通過當前文檔進行搜索,並且無法找到有關使用此方面的信息跨多個文檔。

這些方法中的任何一種都可以通過多個文檔搜索重複元素文本嗎?

非常感謝您的幫助。

回答

3

基本上按鍵是按每個文檔構建的,因此基於直接鍵的Muenchian分組不會允許您在多個文檔中識別和刪除重複項。

然而,您可以先將兩個文檔合併爲一個,然後將Muenchian分組應用到合併文檔。

如果你想在一個樣式表中合併和組需要使用exsl:node-set或類似:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"> 

    <xsl:output method="xml" indent="yes" /> 
    <xsl:key name="Record-by-Description" match="Record" use="Description"/> 

    <xsl:template match="/"> 
    <xsl:variable name="merged-rtf"> 
     <Main> 
     <xsl:copy-of select="document(list/entry/@name)/Main/Records"/> 
     </Main> 
    </xsl:variable> 
    <xsl:apply-templates select="exsl:node-set($merged-rtf)/Main"/> 
    </xsl:template> 

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

    <xsl:template match="Main"> 
    <table> 
     <tr> 
     <th>Type</th> 
     <th>Count</th> 
     </tr> 
     <xsl:apply-templates select="Records"/> 
    </table> 
    </xsl:template> 

    <xsl:template match="Records"> 
    <xsl:apply-templates select="Record[generate-id() = generate-id(key('Record-by-Description', Description)[1])]" mode="group"/> 
    </xsl:template> 

    <xsl:template match="Record" mode="group"> 
    <tr> 
     <td> 
     <xsl:value-of select="Description"/> 
     </td> 
     <td> 
     <xsl:value-of select="count(key('Record-by-Description', Description))"/> 
     </td> 
    </tr> 
    </xsl:template> 

</xsl:stylesheet> 

現在將通過您的INDEX.XML作爲主要輸入文檔樣式表。

如果你想要做的IE瀏覽器這種轉變則需要更換exsl:node-set與微軟的ms:node-set(用正確的命名空間),或者你需要使用的方法在http://dpcarlisle.blogspot.de/2007/05/exslt-node-set-function.html以確保exsl:node-set功能實現。

+0

非常感謝你,這個工程就像預期。 – user2795778

2

如果可以的話,儘管已經用Muenchian方法回答了這個問題,12年來我一直在郵件列表(例如http://www.sourceware.org/ml/xsl-list/2001-10/msg00933.html)和教室中推廣基於變量的XSLT 1.0分組方法。

基於變量的分組方法允許您在一次傳遞中跨多個文件進行分組。使用基於變量的方法進行子組也很簡單。無論你可以解決哪些人口可以放入一個變量,然後分組方法對該變量起作用。

我希望下面的說明文字有助於......你可以看到樣式表非常緊湊,你不需要兩次通過,也不需要使用任何擴展。

數據:

t:\ftemp>type multi.xml 
<?xml-stylesheet type="text/xsl" href="merge2.xsl"?> 
<list> 
    <entry name="File1.xml" /> 
    <entry name="File2.xml" /> 
</list> 

t:\ftemp>type File1.xml 
<Main> 
    <Records> 
     <Record> 
      <Description>A</Description> 
     </Record> 
     <Record> 
      <Description>A</Description> 
     </Record> 
     <Record> 
      <Description>B</Description> 
     </Record> 
     <Record> 
      <Description>C</Description> 
     </Record> 
    </Records> 
    <Records> 
     <Record> 
      <Description>B</Description> 
     </Record> 
     <Record> 
      <Description>A</Description> 
     </Record> 
     <Record> 
      <Description>C</Description> 
     </Record> 
     <Record> 
      <Description>C</Description> 
     </Record> 
    </Records> 
</Main> 

結果:

t:\ftemp>call xslt multi.xml multi.xsl 
<?xml version="1.0" encoding="utf-8"?> 
<table> 
    <tr> 
     <th>Type</th> 
     <th>Count</th> 
    </tr> 
    <tr> 
     <td>A</td> 
     <td>6</td> 
    </tr> 
    <tr> 
     <td>B</td> 
     <td>4</td> 
    </tr> 
    <tr> 
     <td>C</td> 
     <td>6</td> 
    </tr> 
</table> 

樣式表:

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

    <xsl:template match="list"> 
    <table> 
     <tr> 
     <th>Type</th> 
     <th>Count</th> 
     </tr> 
     <xsl:variable name="records" 
          select="document(entry/@name)/Main/Records/Record"/> 

     <xsl:for-each select="$records"> 
     <xsl:if test=" 
        generate-id(.)= 
        generate-id($records[Description=current()/Description][1])"> 
      <tr> 
      <td> 
       <xsl:value-of select="Description"/> 
      </td> 
      <td> 
       <xsl:value-of 
        select="count($records[Description=current()/Description])"/> 
      </td> 
      </tr> 
     </xsl:if> 
     </xsl:for-each> 
    </table> 
    </xsl:template> 

    </xsl:stylesheet> 
+0

這可能是舊的,但謝謝你。我一直在爲此工作數小時。我不能使用'exsl',這是一個非常簡單的解決方案。爲我完美工作。 –