2017-02-09 49 views
0

請建議,如何使用xsl:key(我從變量方法得到結果,但它不是一種有效的方法)避免重複的元素列表。請建議。如何使用xsl:key獲取元素的唯一結構

在我的輸入中,'Ref'是主要元素,它有幾個後代。只需列出'Ref'元素,其結構(只有元素名稱,而不是內容)是唯一的。如果<參考> <一個 /一個> <b/B> < /參考>和<參考> <一個 /一個> <b/B> < /參考>,然後應僅顯示第一個<參考號>。在給定的輸入中,忽略'au'和'ed'元素作爲他們的祖先。

輸入XML:

<article> 
<Ref id="ref1"> 
    <RefText> 
     <authors><au><snm>Kishan</snm><fnm>TR</fnm></au><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2016</Year><vol>1</vol> 
     <fpage>12</fpage><lpage>14</lpage> 
    </RefText></Ref><!-- should list --> 

<Ref id="ref2"> 
    <RefText> 
     <authors><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year><vol>2</vol> 
     <fpage>22</fpage><lpage>24</lpage> 
     </RefText></Ref><!-- This Ref should not list in output xml, because 'authors, articleTitle, like other same type elements present, ref2 is same as ref1. --> 

<Ref id="ref3"> 
    <RefText> 
     <authors><au><snm>Likhith</snm><fnm>MD</fnm></au></authors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year><fpage>22</fpage><lpage>24</lpage> 
     </RefText></Ref><!-- It should list, bcs, 'vol' missing here, then it is unique in structure with respect to prev Refs --> 

<Ref id="ref4"> 
    <RefText> 
     <authors><au><snm>Kowshik</snm><fnm>MD</fnm></au></authors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year><fpage>22</fpage> 
     </RefText></Ref><!-- should list, bcs, 'lpage' missing --> 

<Ref id="ref5"> 
    <RefText> 
     <editors><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year><fpage>22</fpage> 
     </RefText></Ref><!-- should list, bcs, 'editors' missing --> 

<Ref id="ref6"> 
    <RefText> 
     <editors><ed><snm>Kishan</snm><fnm>TR</fnm></ed></editors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year> 
     </RefText></Ref><!-- should list --> 

<Ref id="ref7"> 
    <RefText> 
     <editors><ed><snm>Vivan</snm><fnm>S</fnm></ed></editors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year> 
     </RefText></Ref><!-- should not, same type elements in ref6 and ref7 --> 

<Ref id="ref8"> 
    <RefText><editors><au><snm>Dhyan</snm><fnm>MD</fnm></au><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year><fpage>22</fpage> 
     </RefText></Ref><!-- should not, bcs, 'Ref5 and Ref8' are having same elements --> 

</article> 

XSLT 2.0: 在這裏,我也考慮變量來店前參考的後裔的名字。

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

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

<xsl:template match="article"> 
    <article> 

     <xsl:for-each select="descendant::Ref"> 
      <xsl:variable name="varPrev"> 
      <xsl:for-each select="preceding::Ref"> 
       <a> 
        <xsl:text>|</xsl:text> 
         <xsl:for-each select="descendant::*[not(ancestor-or-self::au) and not(ancestor-or-self::ed)]"> 
          <xsl:value-of select="name()"/> 
         </xsl:for-each> 
        <xsl:text>|</xsl:text> 
       </a> 
      </xsl:for-each> 
     </xsl:variable> 
      <xsl:variable name="varPresent"> 
       <a> 
        <xsl:text>|</xsl:text> 
         <xsl:for-each select="descendant::*[not(ancestor-or-self::au) and not(ancestor-or-self::ed)]"> 
          <xsl:value-of select="name()"/> 
         </xsl:for-each> 
        <xsl:text>|</xsl:text> 
       </a> 
      </xsl:variable> 
      <xsl:if test="not(contains($varPrev, $varPresent))"> 
       <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy> 
      </xsl:if> 

     </xsl:for-each> 
    </article> 
</xsl:template> 

<!--xsl:key name="keyRef" match="Ref" use="descendant::*"/> 

<xsl:template match="article"> 
    <xsl:for-each select="descendant::Ref"> 
     <xsl:if test="count('keyRef', ./name())=1"> 
      <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template--> 

</xsl:stylesheet> 

要求的結果:

<article> 
<Ref id="ref1"> 
    <RefText> 
     <authors><au><snm>Kishan</snm><fnm>TR</fnm></au><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2016</Year><vol>1</vol> 
     <fpage>12</fpage><lpage>14</lpage> 
    </RefText></Ref> 
<Ref id="ref3"> 
    <RefText> 
     <authors><au><snm>Likhith</snm><fnm>MD</fnm></au></authors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year><fpage>22</fpage><lpage>24</lpage> 
     </RefText></Ref> 
<Ref id="ref4"> 
    <RefText> 
     <authors><au><snm>Kowshik</snm><fnm>MD</fnm></au></authors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year><fpage>22</fpage> 
     </RefText></Ref> 
<Ref id="ref5"> 
    <RefText><editors><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year><fpage>22</fpage> 
     </RefText></Ref> 
<Ref id="ref6"> 
    <RefText> 
     <editors><ed><snm>Kishan</snm><fnm>TR</fnm></ed></editors> 
     <artTitle>The article1</artTitle><jTitle>Journal title</jTitle> 
     <Year>2017</Year> 
     </RefText></Ref> 
</article> 
+0

究竟你的意思是「*忽略' au'和'ed'元素作爲它們的祖先。*「?你想考慮整個結構嗎?如果沒有,那麼排除它的某些部分的確切邏輯是什麼? - 另外,每個'Ref'中元素的*順序*是否相同? –

+0

** 1。**考慮只有'作者'的名字,如果兩個,三個,更多的也只是一個主要'作者'組。由於參考文獻可能有不同數量的作者,但'vol''page'其他元素可能相同。 ** 2。**順序的不同也是唯一的,即'a,b'與'b,a'是唯一的。 (訂單有所不同,那麼需要視爲唯一)。 –

+0

我不明白#1。我懷疑,如果刪除文本值(+您不想考慮的那些元素),並對結果節點進行「深度平等()」比較,則可能會得到預期結果。 –

回答

1

下面是使用類似的計算,以你的字符串比較關鍵的嘗試:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:mf="http://example.com/mf" exclude-result-prefixes="mf xs"> 

    <xsl:function name="mf:fingerprint" as="xs:string"> 
     <xsl:param name="input-element" as="element()"/> 
     <xsl:value-of select="for $d in $input-element/descendant::*[not(ancestor-or-self::au) and not(ancestor-or-self::ed)] return node-name($d)" separator="|"/> 
    </xsl:function> 

    <xsl:key name="group" match="Ref" use="mf:fingerprint(.)"/> 

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

    <xsl:template match="Ref[not(. is key('group', mf:fingerprint(.))[1])]"/> 
</xsl:transform> 

似乎在http://xsltransform.net/bwdwsC作爲做的工作盡我所知,但我不確定名稱的字符串連接是否足以處理所有類型的輸入。

+0

優秀的建議先生,再加上一個。 –

1

我建議以下方法:

  • 去除authorseditors後代,所有的文本節點沿;

  • 比較使用deep-equal()的其餘節點。

這裏有一個簡單的證明了概念:

XSLT 2.0

<xsl:stylesheet version="2.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:template match="/article"> 
    <xsl:variable name="first-pass"> 
     <xsl:apply-templates mode="first-pass"/> 
    </xsl:variable> 
    <xsl:copy> 
     <xsl:for-each select="$first-pass/Ref[not(some $ref in preceding-sibling::Ref satisfies deep-equal(RefText, $ref/RefText))]"> 
      <Ref id="{@id}"/> 
     </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

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

<xsl:template match="authors | editors" mode="first-pass"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="text()" mode="first-pass" priority="0"/> 

</xsl:stylesheet> 

結果

<?xml version="1.0" encoding="UTF-8"?> 
<article> 
    <Ref id="ref1"/> 
    <Ref id="ref3"/> 
    <Ref id="ref4"/> 
    <Ref id="ref5"/> 
    <Ref id="ref6"/> 
</article> 
+0

感謝深等的建議,先生。 –

相關問題