【问题标题】:XSLT: Remove duplicate nodes based on name attributeXSLT:根据名称属性删除重复节点
【发布时间】:2011-10-07 17:28:32
【问题描述】:

我有下面需要用 xslt 转换的输入 XML

输入 Xml:

<result>
    <circuit>MX123456</circuit>
    <psaresult>
        <Live_Alarms>
            <diagnosis>
                <utr>xxx</utr>
                <dtr>xxx</dtr>
                <text />
                <site>xxx</site>
                <address />
                <tech_type />
                <end />
                <network_type>xxx</network_type>
            </diagnosis>
            <Alarms>
                <alarmId>463</alarmId>
                <cct>xxx</cct>
                <eventTime>12/05/11 09:21:21</eventTime>
                <clearTime />
                <problemCode>xxxx</problemCode>
                <problemText>xxxx</problemText>
                <equipmentName>xxx</equipmentName>
                <unit>xxx</unit>
                <rcKey>xxx</rcKey>
                <category>xxx</category>
                <rootCause>xxxx</rootCause>
            </Alarms>
            <Alarms>
                <alarmId>464</alarmId>
                <cct>xxx</cct>
                <eventTime>12/05/11 09:21:22</eventTime>
                <clearTime />
                <problemCode>yyyy</problemCode>
                <problemText>yyyy</problemText>
                <equipmentName>yyyy</equipmentName>
                <unit>yyyy</unit>
                <rcKey>yyyy</rcKey>
                <category>yyyy</category>
                <rootCause>yyyy</rootCause>
            </Alarms>
        </Live_Alarms>
    </psaresult>
</result>

预期输出:

<result>
    <circuit>MX123456</circuit>
    <psaresult>
        <Live_Alarms>
            <psadiagnosis>
                <utr>xxx</utr>
                <dtr>xxx</dtr>
                <text />
                <site>xxx</site>
                <address />
                <tech_type />
                <end />
                <network_type>xxx</network_type>
            </psadiagnosis>
            <Alarms>
                <alarmId>463</alarmId>
                <cct>xxx</cct>
                <eventTime>12/05/11 09:21:21</eventTime>
                <clearTime />
                <problemCode>xxxx</problemCode>
                <problemText>xxxx</problemText>
                <equipmentName>xxx</equipmentName>
                <unit>xxx</unit>
                <rcKey>xxx</rcKey>
                <category>xxx</category>
                <rootCause>xxxx</rootCause>
            </Alarms>
        </Live_Alarms>
    </psaresult>
</result>

注意:只需要第一个 Alarms 节点,就像 SelectSinglenode 所做的那样,所有其他节点都需要从输出中截断。您能否告知如何通过 xslt 实现这一点?

【问题讨论】:

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

标签: xml xslt xpath


【解决方案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:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="Alarms[position() >1]"/>
</xsl:stylesheet>

应用于提供的 XML 文档时

<result>
    <circuit>MX123456</circuit>
    <psaresult>
        <Live_Alarms>
            <diagnosis>
                <utr>xxx</utr>
                <dtr>xxx</dtr>
                <text />
                <site>xxx</site>
                <address />
                <tech_type />
                <end />
                <network_type>xxx</network_type>
            </diagnosis>
            <Alarms>
                <alarmId>463</alarmId>
                <cct>xxx</cct>
                <eventTime>12/05/11 09:21:21</eventTime>
                <clearTime />
                <problemCode>xxxx</problemCode>
                <problemText>xxxx</problemText>
                <equipmentName>xxx</equipmentName>
                <unit>xxx</unit>
                <rcKey>xxx</rcKey>
                <category>xxx</category>
                <rootCause>xxxx</rootCause>
            </Alarms>
            <Alarms>
                <alarmId>464</alarmId>
                <cct>xxx</cct>
                <eventTime>12/05/11 09:21:22</eventTime>
                <clearTime />
                <problemCode>yyyy</problemCode>
                <problemText>yyyy</problemText>
                <equipmentName>yyyy</equipmentName>
                <unit>yyyy</unit>
                <rcKey>yyyy</rcKey>
                <category>yyyy</category>
                <rootCause>yyyy</rootCause>
            </Alarms>
        </Live_Alarms>
    </psaresult>
</result>

产生了想要的、正确的结果

<result>
   <circuit>MX123456</circuit>
   <psaresult>
      <Live_Alarms>
         <diagnosis>
            <utr>xxx</utr>
            <dtr>xxx</dtr>
            <text/>
            <site>xxx</site>
            <address/>
            <tech_type/>
            <end/>
            <network_type>xxx</network_type>
         </diagnosis>
         <Alarms>
            <alarmId>463</alarmId>
            <cct>xxx</cct>
            <eventTime>12/05/11 09:21:21</eventTime>
            <clearTime/>
            <problemCode>xxxx</problemCode>
            <problemText>xxxx</problemText>
            <equipmentName>xxx</equipmentName>
            <unit>xxx</unit>
            <rcKey>xxx</rcKey>
            <category>xxx</category>
            <rootCause>xxxx</rootCause>
         </Alarms>
      </Live_Alarms>
   </psaresult>
</result>

解释

  1. identity rule(模板)“按原样”复制每个节点。

  2. 有一个模板覆盖了身份规则。它匹配任何不是其父级的第一个Alarms 子级的Alarms 元素。此模板没有正文 - 有效地丢弃任何此类匹配的元素,以免被复制到输出中。

【讨论】:

    【解决方案2】:

    使用这个:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >
        <xsl:output method="xml" indent="yes"/>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()[not(self::Alarms)] | Alarms[1]"/>
            </xsl:copy>
        </xsl:template>
    
    </xsl:stylesheet>
    

    输出 XML:

    <?xml version="1.0" encoding="utf-8"?>
    <result>
        <circuit>MX123456</circuit>
        <psaresult>
            <Live_Alarms>
                <diagnosis>
                    <utr>xxx</utr>
                    <dtr>xxx</dtr>
                    <text />
                    <site>xxx</site>
                    <address />
                    <tech_type />
                    <end />
                    <network_type>xxx</network_type>
                </diagnosis>
                <Alarms>
                    <alarmId>463</alarmId>
                    <cct>xxx</cct>
                    <eventTime>12/05/11 09:21:21</eventTime>
                    <clearTime />
                    <problemCode>xxxx</problemCode>
                    <problemText>xxxx</problemText>
                    <equipmentName>xxx</equipmentName>
                    <unit>xxx</unit>
                    <rcKey>xxx</rcKey>
                    <category>xxx</category>
                    <rootCause>xxxx</rootCause>
                </Alarms>
    
    
            </Live_Alarms>
        </psaresult>
    
    </result>
    

    【讨论】:

    • 我碰巧使用了这个,它工作了 。谢谢。我是否需要对此进行修改,还有其他 cmets 吗?
    • @Jaisal,它将复制第一个 Alarms 节点。
    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多