【问题标题】:XSLT remove duplicate nodes based on element valueXSLT 根据元素值删除重复节点
【发布时间】:2014-11-06 20:46:29
【问题描述】:

我是 XSLT 的新手。你能帮我让 xslt 实现以下输出吗?在我的输入 xml 中有重复的节点,我必须删除基于元素 (CustAccId) 值不应该重复。

输入xml:

        <Main>
 <Request>
    <TypeInd>I</TypeInd> 
    <CustAcctID>505665599</CustAcctID> 
     <ServiceOrderID>1452653</ServiceOrderID> 
  </Request>
  <Request>
  <TypeInd>O</TypeInd> 
  <CustAcctID>2011395</CustAcctID> 
   <ServiceOrderID>1452652</ServiceOrderID> 
       </Request>
     <Request>
    <TypeInd>I</TypeInd> 
   <CustAcctID>505665599</CustAcctID> 
    <ServiceOrderID>1452653</ServiceOrderID> 
       </Request>
       </Main> 

输出 XML:

 <Main>
      <Request>
         <TypeInd>I</TypeInd> 
         <CustAcctID>505665599</CustAcctID> 
        <ServiceOrderID>1452653</ServiceOrderID> 
   </Request>
 <Request>
       <TypeInd>O</TypeInd> 
       <CustAcctID>2011395</CustAcctID> 
         <ServiceOrderID>1452652</ServiceOrderID> 
  </Request>

Here is XSLt i tried but didn't work like it retrun duplicate request node

   <?xml version="1.0" encoding="UTF-8"?>
       <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
      <xsl:template match="@*|node()">
     <xsl:copy>
         <xsl:apply-templates select="@*|node()" />
      </xsl:copy>
     </xsl:template>
     <xsl:template match="/">
     <xsl:if test="not(following::Request[CustAcctID=current()])">
     <xsl:copy>
       <xsl:apply-templates select="@*|node()" />
      </xsl:copy>
    </xsl:if>
 </xsl:template>
 </xsl:stylesheet>

【问题讨论】:

  • 我建议你先阅读Muenchian grouping;然后在这里搜索之前发布的大量示例。

标签: xslt


【解决方案1】:

您可以使用以下 XSLT 删除重复项:

<xsl:stylesheet version="1.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="@*|node()">
<xsl:copy>
     <xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Request[CustAcctID = following::Request/CustAcctID]"/>  
</xsl:stylesheet>

输出 XML:

<?xml version="1.0" encoding="UTF-8"?>
<Main>
  <Request>
    <TypeInd>O</TypeInd> 
    <CustAcctID>2011395</CustAcctID> 
    <ServiceOrderID>1452652</ServiceOrderID> 
  </Request>
  <Request>
    <TypeInd>I</TypeInd> 
    <CustAcctID>505665599</CustAcctID> 
    <ServiceOrderID>1452653</ServiceOrderID> 
  </Request>
</Main>

模板匹配所有CustAcctID 与以下RequestCustAcctID 匹配的节点,不会为匹配的Request 生成任何输出,因此不会写入重复项。

更新以获取 michael.hor257k 评论中的建议:另一种方法是使用 Muenchian 分组:

<xsl:stylesheet version="1.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:key name="x" match="ServiceOrderID" use="." />
<xsl:template match="@*|node()">
<xsl:copy>
   <xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template> 
<xsl:template match="Request">
<xsl:for-each select=".">
  <xsl:if test="generate-id(ServiceOrderID) =
                generate-id(key('x', ServiceOrderID)[1])">
     <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
     </xsl:copy>
  </xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

它产生相同的输出 XML,但效率更高,您可以在 Jeni Tennison http://www.jenitennison.com/xslt/grouping/muenchian.xml 的文章中找到详细描述,michael.hor257k 已经推荐。

作为 XSLT 分组的附加参考,您可以查看 http://www.dpawson.co.uk/xsl/sect2/N4486.html

【讨论】:

  • @michael.hor257k 感谢提及,已经这样做了;由于获得所需结果的方法不止一种,我想使用 M. 分组而不是应用空模板来过滤掉重复项是有优势的,例如使用 M. 分组可能更有效。
  • OTOH,您的原始解决方案很优雅 (+1),过早的优化很少有回报。
  • @kjhughes 我不认为 Muenchian 分组是“过早的优化”或优化 - 它只是一个更有效的解决方案。由于它不承担任何额外费用,因此短期内是否支付并不重要。
  • 程序上偏向的 Muenchian 解决方案在性能改进方面更为出色,但放弃声明式模式匹配的优雅,确实有成本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-07
  • 2021-05-17
  • 2020-08-23
  • 2011-07-01
  • 2013-12-02
  • 1970-01-01
相关资源
最近更新 更多