2012-03-28 41 views
0

希望找到上師的幫助來找出下一個問題。XSLT苟平,for-each和牽連循環。如何消除重複?

我有兩個xml文件。 Firts一個在這裏(text.xml):

<text> 
<ref>Author1, Title1, Date1</ref> 
<ref>Author75, Title75, Date2</ref> 
<ref>Author2, Title2, Date2</ref> 
<ref>Author3, Title3, Date3</ref> 
<text> 

,第二個這樣的(list.xml):

<list> 
<bibl xml:id="1"><author>Author1</author><date>Date1</date></bibl> 
<bibl xml:id="2"><author>Author2</author><date>Date2</date></bibl> 
<bibl xml:id="3"><author>Author3</author><date>Date3</date></bibl> 
</list> 

我想查詢text.xml和檢查(從list.xml)id來<ref>(從text.xml)WIC:對list.xml添加@xml h包含相同的作者和日期。如果不是,那麼只需複製原始<ref>

所以我想獲得:

<ref xml:id="1">Author1, Title1, Date1</ref> 
<ref>Author75, Title75, Date2</ref> 
<ref xml:id="2>Author2, Title2, Date2</ref> 
etc. 

XSLT識別以及所有correpondence:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

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

    <xsl:template match="ref"> 
     <xsl:variable name="ref" select="."/> 
     <xsl:for-each select="document('list.xml')//bibl"> 
      <xsl:variable name="bibl" select="."/> 
      <xsl:variable name="author" select="author"/> 
      <xsl:variable name="date" select="date"/> 
      <xsl:choose> 
       <xsl:when test="contains($ref, $author) and contains($ref, $date)"> 
        <ref> 
         <xsl:attribute name="xml:id"> 
          <xsl:value-of select="$bibl/@xml:id"/> 
         </xsl:attribute> 
         <xsl:value-of select="$ref"/> 
        </ref> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:copy-of select="$ref"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

但是,再就是沒有correpondence它不只是複製權<ref>,但複製全部<ref>我在第二個文件中有<bibl>個節點的時間數。

所以問題在<xsl:otherwise><xsl:copy-of select="$ref"/></xsl:otherwise>。 任何想法如何才能獲得我需要的獨特價值?我知道它實際上必須非常簡單,我嘗試了key,generate-id,for-each-group,distinct-values,但無法弄清楚。

回答

0

的問題是,要創建一個REF元件爲的for-each循環的每次迭代是否存在匹配或沒有。

你需要在這種情況下,做的是創造ref的的for-each,然後只創建一個循環內的匹配元素的id屬性

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ref"> 
     <xsl:variable name="ref" select="."/> 
     <ref> 
     <xsl:apply-templates select="@* "/> 
     <xsl:for-each select="document('list.xml')//bibl"> 
      <xsl:variable name="bibl" select="."/> 
      <xsl:variable name="author" select="author"/> 
      <xsl:variable name="date" select="date"/> 
      <xsl:choose> 
       <xsl:when test="contains($ref, $author) and contains($ref, $date)"> 
        <xsl:attribute name="xml:id"> 
        <xsl:value-of select="$bibl/@xml:id"/> 
        </xsl:attribute> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
     <xsl:apply-templates select="node()"/> 
     </ref> 
    </xsl:template> 
</xsl:stylesheet> 

應用在室外時元素到示例XML,下面是輸出

<text> 
    <ref xml:id="1">Author1, Title1, Date1</ref> 
    <ref>Author75, Title75, Date2</ref> 
    <ref xml:id="2">Author2, Title2, Date2</ref> 
    <ref xml:id="3">Author3, Title3, Date3</ref> 
</text> 

然而,當前的方法不是很有效,因爲爲每個REF您正在迭代的元素全部爲bibl元素。另一種方法是提取從裁判元素的作者和日期,然後擡頭看bibl元素直接

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ref"> 
     <xsl:variable name="author" select="normalize-space(substring-before(., ','))"/> 
     <xsl:variable name="date" select="normalize-space(substring-after(substring-after(., ','), ','))"/> 
     <ref> 
     <xsl:apply-templates select="@* "/> 
     <xsl:apply-templates select="document('list.xml')//bibl[author=$author][date=$date]"/> 
     <xsl:apply-templates select="node()"/> 
     </ref> 
    </xsl:template> 

    <xsl:template match="bibl"> 
     <xsl:attribute name="xml:id"> 
     <xsl:value-of select="@xml:id"/> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

這也應該給予同樣的結果。

+0

非常感謝你!它工作完美! 完全同意你的第二個解決方案更加優雅和高效。但實際上第一個XML文件(** text.xml **)它只是一個示例。真正的''這就像' J. Smith,Book title,Publisher,2001,p.211'或' Book title,eds。史密斯約翰,2005'等等。所以我現在不是真的可以在哪裏找到作者或日期,我只知道它在某處。 再次感謝您! – 2012-03-28 17:14:19

0

編輯: 姆......過於注重語法XSL,我應該已經看到,早... 你必須在每個ref的牽連外循環,並在每個bibl內部循環。無論匹配還是不匹配,您都會爲每refbibl生成一個元素。 因此,代替xsl:otherwise,您需要在for-each循環之後進行檢查,以查看是否存在匹配,並在需要時執行copy-of

不知道該怎麼做了檢查,though..maybe使用position()和生成的<ref> S的count(),對不起...沒有任何更多的時間,現在想想這個權利。

不是一個真正的解釋,但有解決方法:

<xsl:otherwise> 
    <ref> 
     <xsl:value-of select="$ref"/> 
    </ref> 
</xsl:otherwise> 

我的猜測是,問題就出在$裁判,這是不是在那一刻XPath表達式(如果我沒有記錯的XSL-T )

+0

謝謝你的回答,但仍然有所有的多個副本。我想這是每個$ ref唯一ID的問題。 – 2012-03-28 15:38:19

+0

是的,這正是我的問題,你很好。我試過與contains()和not(contains())而不是,但仍然有相同的問題。無論如何,謝謝你的時間。 – 2012-03-28 16:40:44