xsl:删除当前节点的重复出现

时间:2017-12-23 01:26:55

标签: xml xslt tei

在这篇帖子Compare variable in preceding-sibling with current node之后,我尝试比较当前节点,以便删除重复的帖子。

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE stylesheet [
 <!ENTITY menu SYSTEM "verb.xml">   
]>    

<xsl:variable name="gram" as="xs:string*" select="*//gramGrp/string-join((iType/@value, mood/@value, tns/@value, subc/@value), '. ')"/>
<xsl:variable name="actor-affixes" as="xs:string*" select="*//gramGrp/string-join((per/@value, gen/@value, number/@value), '')"/>

<xsl:for-each select="w[@n | @lemma]">

  <ul>
    <li><xsl:variable name="inflected">
       <xsl:for-each select="*/m[@type='pref']"> 
         <xsl:value-of select="current()"/>
           <xsl:choose>
             <xsl:when test="."><xsl:text>-</xsl:text></xsl:when>
             <xsl:otherwise/>
           </xsl:choose>
        </xsl:for-each> 

        <xsl:for-each select="*//m[@type='baseForm']"> 
          <xsl:variable name="str1">
            <xsl:value-of select="current()[not != c[@type['infix']]] |node()"/>
          </xsl:variable>
          <xsl:value-of select="translate(normalize-space($str1), ' ', '-')"/>  
        </xsl:for-each>

        <xsl:for-each select="*//m[@type='suff']">
            <xsl:variable name="str2">
              <xsl:if test="position() = last()"><xsl:text>-</xsl:text><xsl:value-of select="."/></xsl:if>
            </xsl:variable>
            <xsl:value-of select="concat($str2, '')"/>  
        </xsl:for-each>

        </xsl:variable>
        <xsl:value-of select="$inflected"/>

        <xsl:text>: </xsl:text>

        <xsl:variable name="gram-affixes">            
          <xsl:if test="$gram = preceding-sibling::node()/$gram">
            <xsl:value-of select="$gram"/>
          </xsl:if>
          <xsl:text>.</xsl:text>
          <xsl:value-of select="$actor-affixes" separator=", "/><xsl:text>.</xsl:text>
        </xsl:variable>
        <xsl:value-of select="$gram-affixes"/>
     </li>
  </ul>
</xsl:for-each>

来自TEI-XML

的内容
<w n="1" lemma="tmtḫṣ" xml:id="tmtḫṣ" ana="#mḫṣ">
  <m type="base">
    <m type="pref" ana="#pref-t">t</m>
    <m type="baseForm">m<c type="infix" ana="#infix-t">t</c>ḫṣ</m>
  </m>               
</w>
<w n="2" lemma="tmḫṣ" xml:id="tmḫṣ" ana="#mḫṣ">
   <m type="base">
     <m type="pref" ana="#pref-t">t</m>
     <m type="baseForm">mḫṣ</m>
   </m>
</w>
<gramGrp type="baseForm" ana="#mḫṣ">
   <gramGrp n="1" ana="#tmtḫṣ">
     <iType ana="#sstem.Gt" value="Gt" type="semantic-variations"/>
     <mood ana="#mood.ind" value="ind"/>
     <tns ana="#sasp.imperf" value="imperf"/>
     <subc ana="#strans" value="trans"/>
     <gramGrp n="1.1" ana="#actor-affixes">
        <per ana="#s2" value="2"/>
        <gen ana="#smasc" value="m"/>
        <number ana="#ssing" value="sg"/>
     </gramGrp>
     <gramGrp n="1.2" ana="#actor-affixes">
        <per ana="#s3" value="3"/>
        <gen ana="#sfem" value="f"/>
        <number ana="#ssing" value="sg"/>
     </gramGrp>
    </gramGrp>
  <gramGrp n="2" ana="#tmḫṣ">
     <iType ana="#sstem.D" value="D" type="semantic-variations"/>
     <mood ana="#mood.ind" value="ind"/>
     <tns ana="#sasp.perf" value="perf"/>
     <subc ana="#strans" value="trans"/>
     <gramGrp n="1.1" ana="#actor-affixes">
        <per ana="#s2" value="2"/>
        <gen ana="#smasc" value="m"/>
        <number ana="#ssing" value="sg"/>
     </gramGrp>
     <gramGrp n="1.2" ana="#actor-affixes">
       <per ana="#s3" value="3"/>
       <gen ana="#sfem" value="f"/>
       <number ana="#ssing" value="sg"/>
      </gramGrp>
    </gramGrp>
</gramGrp>

我也尝试过:<xsl:for-each select="distinct-values($gram)"><xsl:value-of select="normalize-space(.)"/></xsl:for-each>(关注Compare variable in preceding-sibling with current node)和<xsl:for-each select="$gram[not(. = preceding-sibling::node()/$gram)]"><xsl:value-of select="$gram"/></xsl:for-each>。但它不起作用......

目前的输出是:

<ul><li>t-m-t-ḫṣ: Gt. ind. imperf. transD. ind. perf. trans., 2msg, 3fsg, , 2msg, 3fsg.</li></ul>
<ul><li>t-mḫṣ: Gt. ind. imperf. transD. ind. perf. trans., 2msg, 3fsg, , 2msg, 3fsg.</li></ul>

但正如您所看到的,':'后面的事件是相同的。它应该是:

<ul><li>t-m-t-ḫṣ: Gt. ind. imperf. trans., 2msg, 3fsg.</li></ul>
<ul><li>t-mḫṣ: D. ind. perf. trans., 2msg, 3fsg.</li></ul>

更新

根据建议,我已更新新版本,以便包含所有TEI element。它工作正常。但我在评论中添加了<!-- -->其他问题。我想我仍然不明白key是如何运作的。我不知道是否需要添加新帖子 - 如果是,请道歉 - 你能解释key是如何工作的吗?

TEI:

<entryFree n="6" xml:id="mḫṣ">
  <form type="verb">
    <orth>mḫṣ</orth>
  </form>
  <form type="inflected">
    <w n="1" lemma="tmtḫṣ" xml:id="tmtḫṣ" ana="#mḫṣ">
       <m type="base">
         <m type="pref" ana="#pref-t">t</m>
         <m type="baseForm">m<c type="infix" ana="#infix-t">t</c>ḫṣ</m>
       </m> 
    </w>
    <w n="2" lemma="tmḫṣ" xml:id="tmḫṣ" ana="#mḫṣ">
        <m type="base">
          <m type="pref" ana="#pref-t">t</m>
          <m type="baseForm">mḫṣ</m>
        </m>
    </w>
    <gramGrp type="baseForm" ana="#mḫṣ">
      <gramGrp n="1" ana="#tmtḫṣ">
        <iType ana="#sstem.Gt" value="Gt" type="semantic-variations"/>
        <mood ana="#mood.ind" value="ind"/>
        <tns ana="#sasp.imperf" value="imperf"/>
        <subc ana="#strans" value="trans"/>
        <gramGrp n="1.1" ana="#actor-affixes">
           <per ana="#s2" value="2"/>
           <gen ana="#smasc" value="m"/>
           <number ana="#ssing" value="sg"/>
        </gramGrp>
        <gramGrp n="1.2" ana="#actor-affixes">
           <per ana="#s3" value="3"/>
           <gen ana="#sfem" value="f"/>
           <number ana="#ssing" value="sg"/>
        </gramGrp>
       </gramGrp>
       <gramGrp n="2" ana="#tmḫṣ">
         <iType ana="#sstem.D" value="D" type="semantic-variations"/>
         <mood ana="#mood.ind" value="ind"/>
         <tns ana="#sasp.perf" value="perf"/>
         <subc ana="#strans" value="trans"/>
         <gramGrp n="1.1" ana="#actor-affixes">
           <per ana="#s2" value="2"/>
           <gen ana="#smasc" value="m"/>
           <number ana="#ssing" value="sg"/>
         </gramGrp>
         <gramGrp n="1.2" ana="#actor-affixes">
           <per ana="#s3" value="3"/>
           <gen ana="#sfem" value="f"/>
           <number ana="#ssing" value="sg"/>
         </gramGrp>
        </gramGrp>
       </gramGrp>
      </form>
      <sense n="1" ana="#mḫṣ" xml:id="mḥṣ01">to fight</sense>
      <sense n="2" ana="#mḥṣ" xml:id="mḥṣ02">to destroy</sense>
       <re n="1" ana="#tmtḫṣ #mḫṣ01" type="inflected" >
        <sense>She fought <span>iterative function // with <ref
                    target="../computation/corpus_ilimilku.xml#ktu1-3_ii_l6b_tḫtṣb">tḫtṣb</ref></span>
           <span type="interp"><ref target="../computation/corpus_ilimilku.xml#ktu1-3_ii_l5b_6a_int">Hermeneutics</ref></span>
           <span ana="../computation/corpus_ilimilku.xml#contend"><reftarget="../computation/corpus_ilimilku.xml#mḫṣ01">Taxonomy, subcategory ofcompetition verb: contend</ref></span>
        </sense>
       </re>
       <re n="2" ana="#tmḫṣ #mḫṣ02" type="inflected">
         <sense>She destroyed <span type="interp"><ref target="../computation/corpus_ilimilku.xml#ktu1-3_ii_l7_int">Hermeneutics</ref></span>
            <span ana="../computation/corpus_ilimilku.xml#humiliation"><ref target="../computation/corpus_ilimilku.xml#mḫṣ02">Taxonomy, subcategory of emotion's verb as a concept of: humiliation</ref></span>
         </sense>
        </re>
      </entryFree>

XSL更新:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array" version="3.0">

<xsl:output method="html" encoding="utf-8" doctype system="about:legacy-compat"/>

<xsl:mode on-no-match="shallow-copy"/>
<xsl:key name="gramGrp" match="gramGrp[@n and @ana]" composite="yes" use="@n, substring(@ana, 2)"/>
<!-- <xsl:key name="re" match="re[@n and @ana[1]]" composite="yes" use="@n, substring(@ana, 2)" /> -->



<xsl:template match="entryFree">
     <xsl:variable name="orth" select="*/orth/text()" />
           <h3><xsl:value-of select="$orth"/></h3>
            <xsl:text>&#10; Mean.: </xsl:text><xsl:value-of select="*//following-sibling::sense[@xml:id]" separator=", " /><xsl:text>.</xsl:text>
            <ul><xsl:for-each select="*/w[@n | @lemma]">

                <xsl:variable name="pref" as="xs:string*" select="string-join(m[@type = 'base']/m, '')"/>
                <xsl:variable name="referenced-gramGrp" select="key('gramGrp', (@n, @lemma))"/>
                <xsl:variable name="gram" as="xs:string*" select="$referenced-gramGrp/string-join((iType/@value, mood/@value, tns/@value, subc/@value), '. ')"/>
                <xsl:variable name="actor-affixes" as="xs:string*" select="$referenced-gramGrp/gramGrp/string-join((per/@value, gen/@value, number/@value), '')"/>
                <!-- <xsl:variable name="referenced-re" select="key('re', (ancestor-or-self::w/@xml:id))" />
                <xsl:variable name="trans" as="xs:string*" select="$referenced-re/string-join(following::re/sense, '')"/> -->


                <li>
                    <xsl:value-of select="$pref"/>
                    <xsl:text>: </xsl:text>
                    <xsl:value-of select="$gram, $actor-affixes" separator=", "/>
                    <xsl:text>. </xsl:text>Trans.
                    <!-- <xsl:value-of select="$trans" separator=". "/> --> 

                </li>

            </xsl:for-each></ul>


 </xsl:template>

 <xsl:template match="gramGrp"/>
 <!-- <xsl:template match="re"/> -->

</xsl:stylesheet>

输出:

 <h3>mḫṣ</h3>
 Mean.: to fight, to destroy.
 <ul>
  <li>tmtḫṣ: Gt. ind. imperf. trans, 2msg, 3fsg. Trans.
  <!-- '$trans'-->
  </li>
  <li>tmḫṣ: D. ind. perf. trans, 2msg, 3fsg. Trans.
  <!-- $trans' -->
  </li>
 </ul>

不幸的是,$trans没有输出。我有什么问题? 更新版本可在此处找到:http://xsltfiddle.liberty-development.net/3Nqn5Y4

提前感谢您对xsl新手的支持。

2 个答案:

答案 0 :(得分:1)

有两种方法可以回答这样的问题:(a)指出代码有什么问题,(b)提供有效的解决方案。我打算做(a);也许别人会做(b)。

这里有一些非常可怕的代码。让我们从关键领域开始:

      <xsl:if test="$gram = preceding-sibling::node()/$gram">
        <xsl:value-of select="$gram"/>
      </xsl:if>

在“/”的右侧使用变量引用确实没有意义。实际上,使用任何其值不依赖于上下文项的表达式都没有意义。 X/$gram为您提供包含N次出现$gram的序列(其中N是X的大小),并且由于所有这些都等于$gram,因此您的条件将始终为真。我不知道这段代码试图实现什么。

这里还有其他一些事情没有用处。

   <xsl:choose>
     <xsl:when test="."><xsl:text>-</xsl:text></xsl:when>
     <xsl:otherwise/>
   </xsl:choose>

自“。”是一个节点,其有效布尔值始终为true,因此此代码等效于

<xsl:text>-</xsl:text>

现在:

<xsl:variable name="str1">
      <xsl:value-of select="
          current()[not != c[@type['infix']]] |node()"/>
</xsl:variable>
<xsl:value-of select="
         translate(normalize-space($str1), ' ', '-')"/>

首先,构造

<xsl:variable name="V"><xsl:value-of select="X"/></xsl:variable>

应该几乎总是被重写为

<xsl:variable name="V" select="X"/>

其次,关键字“not”在这里意味着“child :: not” - 它正在寻找一个名为“not”的元素。这是有意的吗?

最后,current()m元素,源中的m元素只有一个文本节点子元素。取一个元素(受条件限制)和它的文本节点子节点的联合,然后形成结果的字符串值,这似乎是一个非常奇怪的操作,很难想象它想要实现什么。

答案 1 :(得分:1)

我认为您希望将变量移动到模板或for-each中,并使用正确的上下文节点,并且您希望使用键引用语法部分,这里是一个XSLT 3样式表(可以使用Saxon 9.8任何版本运行)或早期的PE或EE版本以及Altova 2017或2018)尝试这样做:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="xs math map array"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:key name="gramGrp" match="gramGrp[@n and @ana]" composite="yes" use="@n, substring(@ana, 2)"/>

  <xsl:template match="w[@n | @lemma]">
      <ul>
          <xsl:variable name="pref" as="xs:string" select="string-join(m[@type = 'base']/m, '')"/>
          <xsl:variable name="referenced-gramGrp" select="key('gramGrp', (@n, @lemma))"/>
          <xsl:variable name="gram" as="xs:string*" select="$referenced-gramGrp/string-join((iType/@value, mood/@value, tns/@value, subc/@value), '. ')"/>
          <xsl:variable name="actor-affixes" as="xs:string*" select="$referenced-gramGrp/gramGrp/string-join((per/@value, gen/@value, number/@value), '')"/>
          <li>
              <xsl:value-of select="$pref" separator="-"/>
              <xsl:text>: </xsl:text>
              <xsl:value-of select="$gram, $actor-affixes" separator=", "/>
          </li>

      </ul>
  </xsl:template>

  <xsl:template match="gramGrp"/>

</xsl:stylesheet>

http://xsltfiddle.liberty-development.net/jyyiVhf,您可以看到结果是

<root>
    <ul><li>tmtḫṣ: Gt. ind. imperf. trans, 2msg, 3fsg</li></ul>
<ul><li>tmḫṣ: D. ind. perf. trans, 2msg, 3fsg</li></ul>

</root>

您需要添加代码,将tmtḫṣ等字符串分解为组件,因为我无法弄清楚它是如何工作的。

对于使用其他键编辑的问题,由于re属性中的ana元素具有列表,因此不清楚要选择哪个值来形成键。 IDS。假设您只想使用第一个id作为键值,可以使用

   <xsl:key name="re" match="re[@n and @ana]" composite="yes" use="@n, tokenize(@ana, '\s+')[1]!substring(., 2)" />

然后

<xsl:variable name="referenced-re" select="key('re', (@n, @xml:id))" />

应为您的示例数据找到re元素。

相关问题