2017-02-09 62 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

感谢深等的建议,先生。 –

相关问题