【问题标题】:XML Merge same name elements inside a node using XSLXML 使用 XSL 合并节点内的同名元素
【发布时间】:2012-09-07 11:05:32
【问题描述】:

我有以下xml

<EMPLS>
 <EMPL>
    <NAME>110</NAME>
    <REMARK>R1</REMARK>
  </EMPL>
 <EMPL>
    <NAME>111</NAME>
    <REMARK>R1</REMARK>
    <REMARK>R2</REMARK>
    <REMARK>R3</REMARK>
  </EMPL>
</EMPLS>

并且需要将xml转换成以下格式:

<EMPLS>
 <EMPL>
    <NAME>110</NAME>
    <REMARK>R1</REMARK>
  </EMPL>
 <EMPL>
    <NAME>111</NAME>
    <REMARK>R1 R2 R3</REMARK>
  </EMPL>
</EMPLS>

我是 xsl 的新手,请您告知如何完成。

【问题讨论】:

  • 提供的源 XML 和想要的转换结果都不是格式正确的。请编辑问题并更正。
  • 另外,你能说一下你可以使用XSLT2.0,还是只使用XSLT1.0?谢谢!

标签: xml xslt merge


【解决方案1】:

我这个 XSLT 1.0 转换

<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="kChildByName" match="EMPL/*"
  use="concat(generate-id(..), '+', name())"/>

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

  <xsl:template match="EMPL/*" priority="0"/>

 <xsl:template match=
 "EMPL/*
     [generate-id()
     =
      generate-id(key('kChildByName',
                       concat(generate-id(..), '+', name())
                      )[1]
                  )
      ]">
  <xsl:copy>
   <xsl:for-each select="key('kChildByName',
                             concat(generate-id(..), '+', name())
                         )">
    <xsl:if test="not(position()=1)"><xsl:text> </xsl:text></xsl:if>
    <xsl:value-of select="."/>
   </xsl:for-each>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="EMPL/*" priority="0"/>
</xsl:stylesheet>

应用于所提供的 XML 文档时(已从众多错误中纠正):

<EMPLS>
 <EMPL>
    <NAME>110</NAME>
    <REMARK>R1</REMARK>
  </EMPL>
 <EMPL>
    <NAME>111</NAME>
    <REMARK>R1</REMARK>
    <REMARK>R2</REMARK>
    <REMARK>R3</REMARK>
  </EMPL>
</EMPLS>

产生想要的正确结果

<EMPLS>
   <EMPL>
      <NAME>110</NAME>
      <REMARK>R1</REMARK>
   </EMPL>
   <EMPL>
      <NAME>111</NAME>
      <REMARK>R1 R2 R3</REMARK>
   </EMPL>
</EMPLS>

解释

  1. 正确使用和覆盖 identity rule

  2. 正确使用 Muenchian Grouping method 和复合键。


二。 XSLT 2.0 解决方案:

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

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

 <xsl:template match="EMPL">
  <xsl:copy>
    <xsl:for-each-group select="*" group-by="name()">
     <xsl:copy>
       <xsl:value-of select="current-group()" separator=" "/>
     </xsl:copy>
    </xsl:for-each-group>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

解释

  1. 正确使用&lt;xsl:for-each-group&gt;

  2. 正确使用current-group()函数。

【讨论】:

  • 我有一个疑问。在这个输入中,它正在工作。假设输入像 111R1R2R3222R4 R5R6 输出为 111 222R1 R2 R3 R4 R5 R6 但应该是 111R1 R2 R3222R4 R5 R6 EMPL> 所以请告知如何实现。
  • @ThirusangurajaVenkatesan,您已将原始 XML 源文档的结构更改为您自己的(只有一个 &lt;EMPL&gt; 元素)。为什么您希望解决方案能够在 XML 文档的全新/不同结构中正常工作?如果您有任何问题,请提出问题,不要将代码放在 cmets 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 2020-02-12
相关资源
最近更新 更多