【问题标题】:XSLT 1.0 - Remove duplicates fieldsXSLT 1.0 - 删除重复字段
【发布时间】:2013-03-21 15:33:58
【问题描述】:

我在使用 XSLT V1.0 删除重复节点时遇到问题。我有这个入口

    <?xml version="1.0" encoding="utf-8"?>
<myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Mappings>
        <Mapping fieldName="field1" >
        </Mapping>
        <Mapping fieldName="field1">
        </Mapping>
        <Mapping fieldName="field2" >
        </Mapping>
        <Mapping fieldName="field3" >
        </Mapping>
        <Mapping fieldName="field4">
        </Mapping>
    </Mappings>
</myRoot>

我有这个 XSL 文件

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

    <xsl:output method="xml" encoding="utf-8" indent="yes"/>

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

    <xsl:template match="Mappings">
        <xsl:if test="not(following::Mappings[Mapping/@fieldName=current()/Mapping/@fieldName])">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:if>       
    </xsl:template>


</xsl:stylesheet>

我有与结果相同的条目 XML 文件!

我怎样才能摆脱重复的节点()?

我尝试了一切,但没有结果:(

我试过了 Removing duplicates in xml with xslt Transform to remove duplicate and copy rest Removing consecutive duplicates with XSLT XSLT 1.0 textlist to individual elements and duplicate removal

......

我应该怎么做才能得到这个结果??

 <?xml version="1.0" encoding="utf-8"?>
    <myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <Mappings>
            <Mapping fieldName="field1">
            </Mapping>
            <Mapping fieldName="field2" >
            </Mapping>
            <Mapping fieldName="field3" >
            </Mapping>
            <Mapping fieldName="field4">
            </Mapping>
        </Mappings>
    </myRoot>

谢谢

【问题讨论】:

  • 在我回答问题 18 分钟后,您似乎对问题进行了编辑。我的回答有什么不满意的地方吗?如果您需要像这样分隔元素的标签,可以这样做,但我的答案中的输出在语义上与您那里的输出相同。

标签: xml xslt xslt-1.0


【解决方案1】:

解决方法很简单(没有命名模板也没有使用xsl:call-template,只有两个模板,完全“推式”)

<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="kFieldNameByVal" match="@fieldName" use="."/>

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

  <xsl:template match=
   "Mapping[not(generate-id(@fieldName)
           = generate-id(key('kFieldNameByVal', @fieldName)[1]))]"/>

</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Mappings>
        <Mapping fieldName="field1" >
        </Mapping>
        <Mapping fieldName="field1">
        </Mapping>
        <Mapping fieldName="field2" >
        </Mapping>
        <Mapping fieldName="field3" >
        </Mapping>
        <Mapping fieldName="field4">
        </Mapping>
    </Mappings>
</myRoot>

产生了想要的正确结果:

<myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <Mappings>
      <Mapping fieldName="field1"/>
      <Mapping fieldName="field2"/>
      <Mapping fieldName="field3"/>
      <Mapping fieldName="field4"/>
   </Mappings>
</myRoot>

【讨论】:

  • 感谢您的回答。它工作得很好。现在我想知道如何在特定节点上应用规则。例如我正在使用这个&lt;xsl:template match="/"&gt; &lt;xsl:value-of select="translate(concat(translate(myRoot/@name, $upper, $lower)),translate(concat(translate(myRoot/@name, $upper, $lower)), $AllowedSymbols, ''),'')"/&gt;&lt;xsl:template match="Mapping"&gt; &lt;name&gt; &lt;xsl:value-of select=" translate(concat(translate(@fieldName, $upper, $lower)),translate(concat(translate(@fieldName, $upper, $lower)), $AllowedSymbols, ''),'')"/&gt; &lt;/name&gt; 等。我可以在现有代码上应用这个方法吗?
  • 现在我使用 .xsl 一个用于重复删除,另一个用于我的输出文件
  • @mido,请把你的新问题作为一个 ...new SO 问题提出。 cmets 格式不适合交换代码。
【解决方案2】:

这里的问题是您的模板匹配 Mappings 并试图排除以下重复的 Mappings 元素,但没有。

在任何一种情况下,following::preceding:: 都不是在 XSLT 中选择不同值的好方法。相反,您应该使用Muenchian grouping:

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

  <xsl:key name="kMapping" match="Mapping" use="@fieldName"/>

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

  <xsl:template match="Mapping[generate-id() = 
                               generate-id(key('kMapping', @fieldName)[1])]">
    <xsl:call-template name="Copy" />
  </xsl:template>
  <xsl:template match="Mapping" />
</xsl:stylesheet>

在您的示例输入上运行时,会产生:

<myRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Mappings>
    <Mapping fieldName="field1" />
    <Mapping fieldName="field2" />
    <Mapping fieldName="field3" />
    <Mapping fieldName="field4" />
  </Mappings>
</myRoot>

【讨论】:

  • 感谢您的回答。它工作得很好。现在我想知道如何在特定节点上应用规则。例如我正在使用这个&lt;xsl:template match="/"&gt; &lt;xsl:value-of select="translate(concat(translate(myRoot/@name, $upper, $lower)),translate(concat(translate(myRoot/@name, $upper, $lower)), $AllowedSymbols, ''),'')"/&gt;&lt;xsl:template match="Mapping"&gt; &lt;name&gt; &lt;xsl:value-of select=" translate(concat(translate(@fieldName, $upper, $lower)),translate(concat(translate(@fieldName, $upper, $lower)), $AllowedSymbols, ''),'')"/&gt; &lt;/name&gt; 等。我可以将此方法应用于现有代码吗?
猜你喜欢
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多