【问题标题】:using xslt to remove term if a property of it is a duplicate of another term如果它的属性与另一个术语重复,则使用 xslt 删除术语
【发布时间】:2011-07-07 10:27:28
【问题描述】:

我查看了How to remove duplicate XML nodes using XSLT 和其他相关问题,但如果整个节点是重复的,它们似乎都是关于删除重复的。我想要做的是仅当节点中的一个属性与另一个节点中的属性匹配时才删除节点。

在我的 xml 中,我有 2 个termTypes;钕和铂。应该使用积分。在系统找到 Nd 的地方,不应使用它的 termName,而应使用 relation termName 中引用的 Pt 的名称。

但是出了点问题,一些 Nd 的名称与它们应该引用的 Pts 的名称相同。这些术语无关紧要,我需要删除它们

我有:

<term>
<termId>1</termId>
<termUpdate>Add</termUpdate>
<termName>A</termName>
<termType>Nd</termType>
<relation>
  <relationType>USE</relationType>
  <termId>2</termId>
  <termName>A</termName>
</relation>
</term>

<term>
<termId>2</termId>
<termUpdate>Add</termUpdate>
<termName>A</termName>
<termType>Pt</termType>
</term>

<term>
<termId>3</termId>
<termUpdate>Add</termUpdate>
<termName>C</termName>
<termType>Nd</termType>
<relation>
  <relationType>USE</relationType>
  <termId>4</termId>
  <termName>D</termName>
</relation>
</term>

<term>
<termId>4</termId>
<termUpdate>Add</termUpdate>
<termName>D</termName>
<termType>Pt</termType>
</term>

是否可以使用xslt(或其他方法)来查看,如果Nd &lt;term&gt;&lt;termName&gt; 与其&lt;relation&gt; 中的Pt 术语的&lt;termName&gt; 匹配,则删除整个学期? &lt;relation&gt; 中引用的术语始终是 Pt 术语。

输出:

<term>
<termId>2</termId>
<termUpdate>Add</termUpdate>
<termName>A</termName>
<termType>Pt</termType>
</term>

<term>
<termId>3</termId>
<termUpdate>Add</termUpdate>
<termName>C</termName>
<termType>Nd</termType>
<relation>
  <relationType>USE</relationType>
  <termId>4</termId>
  <termName>D</termName>
</relation>
</term>

<term>
<termId>4</termId>
<termUpdate>Add</termUpdate>
<termName>D</termName>
<termType>Pt</termType>
</term>

谢谢!

【问题讨论】:

  • 好问题,+1。请参阅我的答案,以获得基于最基本和最强大的 XSLT 设计模式的完整、简短和简单的解决方案 - 身份规则的覆盖。

标签: xslt duplicates


【解决方案1】:

这种转变

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kPtByName" match="term[termType='Pt']"
  use="termName"/>

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

 <xsl:template match="term[termType='Nd']">
  <xsl:if test="not(key('kPtByName', termName))">
   <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时(包装到顶部元素中以使其格式正确):

<terms>
    <term>
    <termId>1</termId>
    <termUpdate>Add</termUpdate>
    <termName>A</termName>
    <termType>Nd</termType>
    <relation>
      <relationType>USE</relationType>
      <termId>2</termId>
      <termName>A</termName>
    </relation>
    </term>

    <term>
    <termId>2</termId>
    <termUpdate>Add</termUpdate>
    <termName>A</termName>
    <termType>Pt</termType>
    </term>

    <term>
    <termId>3</termId>
    <termUpdate>Add</termUpdate>
    <termName>C</termName>
    <termType>Nd</termType>
    <relation>
      <relationType>USE</relationType>
      <termId>4</termId>
      <termName>D</termName>
    </relation>
    </term>

    <term>
    <termId>4</termId>
    <termUpdate>Add</termUpdate>
    <termName>D</termName>
    <termType>Pt</termType>
    </term>
</terms>

产生想要的、正确的输出

<terms>
   <term>
      <termId>2</termId>
      <termUpdate>Add</termUpdate>
      <termName>A</termName>
      <termType>Pt</termType>
   </term>
   <term>
      <termId>3</termId>
      <termUpdate>Add</termUpdate>
      <termName>C</termName>
      <termType>Nd</termType>
      <relation>
         <relationType>USE</relationType>
         <termId>4</termId>
         <termName>D</termName>
      </relation>
   </term>
   <term>
      <termId>4</termId>
      <termUpdate>Add</termUpdate>
      <termName>D</termName>
      <termType>Pt</termType>
   </term>
</terms>

解释

  1. identity rule“按原样”复制每个节点

  2. 只有一个模板覆盖了身份模板。它匹配任何termType 子级的值为Ndterm。如果没有与其tername 子级具有相同值的term 并且其termType 子级的值为Pt,则此模板仅调用identity 模板。此测试使用方便定义的xsl:key

  3. 执行

【讨论】:

  • 太棒了,太棒了,很抱歉迟迟没有回复你,我的网络中断了。
【解决方案2】:

这个问题也可以通过考虑我们只在给定条件满足时才需要复制Nd类型的节点来解决。然后我们可以使用xsl:copy-of 来复制想要的节点,并利用XSLT 函数current() 来构建一个有点复杂的XPath。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:include href="identity.xsl"/>

 <xsl:template match="term[termType='Nd']" name="excludeNd">
     <xsl:copy-of select="self::node()
         [ not( ../term
                [ termId = current()/relation/termId ]
                    /termName = current()/termName )
         ]"/>
 </xsl:template>

</xsl:stylesheet>

如果模板exceludeNd 将在输出中包含Nd 类型的术语,当且仅当其关系术语没有相同的名称。

包含的文件identity.xsl 只是一个包含众所周知的身份转换的外部样式表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 2018-04-26
    • 1970-01-01
    相关资源
    最近更新 更多