如何使用XSLT删除XML中的重复字段

时间:2018-08-15 13:45:14

标签: xml xslt

我有这个XML:-

<?xml version="1.0" encoding="UTF-8"?>

 <queryResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns="http://www.force.com/2009/06/asyncapi/dataload">
  <records xsi:type="sObject">
   <type>Task</type>
   <id>1</id>
   <name>1xyz</name>
   <lastname>1abc </lastname>
   <id>1</id>
   </records>
   <records xsi:type="sObject">
   <type>Task</type>
   <id>2</id>
   <name>2xyz</name>
   <lastname>2abc </lastname>
   <id>2</id>
   </records>
   </queryResult>

我想删除同一记录字段中的第二个id标签。所以我想要的xml是:-

<?xml version="1.0" encoding="UTF-8"?>

 <queryResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns="http://www.force.com/2009/06/asyncapi/dataload">
  <records xsi:type="sObject">
   <type>Task</type>
   <id>1</id>
   <name>1xyz</name>
   <lastname>1abc </lastname>
   </records>
   <records xsi:type="sObject">
   <type>Task</type>
   <id>2</id>
   <name>2xyz</name>
   <lastname>2abc </lastname>
  </records>
 </queryResult>

所以基本上我想从我的xml中删除该多余的id标记。

1 个答案:

答案 0 :(得分:3)

由于您未指定XSLT版本,因此我使用的是2.0版。

请注意,您的源XML使用的默认命名空间 http://www.force.com/2009/06/asyncapi/dataload ,因此通常您应该 在stylesheet XSLT元素中提及它。

但是为了简化脚本,您可以将其指定为xpath-default-namespace, 因此您无需将其指定为“常规”命名空间。

编写脚本的想法很简单:编写与records相匹配的模板 (在默认名称空间中,如之前指定的)。该模板应:

  • 复制源代码开始标记。
  • 将模板应用于第一个 id子元素。
  • 将模板应用于除id之外的所有子元素。
  • 复制源结束标记。

您的脚本还应该包括身份模板

因此整个脚本可以如下:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xpath-default-namespace="http://www.force.com/2009/06/asyncapi/dataload">
  <xsl:output method="xml" encoding="UTF-8" indent="yes" />

  <xsl:template match="records">
    <xsl:copy>
      <xsl:apply-templates select="id[1]"/>
      <xsl:apply-templates select="* except id"/>
    </xsl:copy>
  </xsl:template>

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

有关工作示例,请参见http://xsltransform.net/pNvs5wD

编辑

另一种解决方案是编写与id匹配的空模板, 其中的preceding-sibling元素名为id

<xsl:template match="id[preceding-sibling::id]"/>

因此整个脚本可以是:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xpath-default-namespace="http://www.force.com/2009/06/asyncapi/dataload">
  <xsl:output method="xml" encoding="UTF-8" indent="yes" />
  <xsl:strip-space elements="*"/>

  <xsl:template match="id[preceding-sibling::id]"/>

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

区别在于,这次您保持子元素的顺序, 而第一个解决方案将id元素“移动”到开头。

注意:这次我添加了<xsl:strip-space elements="*"/>以避免为空 输出中的行。