使用 XSLT 删除具有相同名称的 XML 层次结构元素



我得到的XML响应在响应中具有相同的命名元素,这导致我出现问题,我需要使用XSLT 1.0删除这个重复出现的元素。响应中有问题的元素是 <RoundIncidents> 。我已经浏览了其他问题,但找不到将响应转换为正确格式所需的内容。

具有重复元素的 XML 响应

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Body>
      <GetSiteIncidentsResponse xmlns="http://webservices.whitespacews.com/">
         <GetSiteIncidentsResult>
            <ErrorCode>0</ErrorCode>
            <ErrorDescription>Success</ErrorDescription>
            <SuccessFlag>true</SuccessFlag>
            <RoundIncidents>
               <RoundIncidents>
                  <ExtensionData />
                  <AccountSiteID>0</AccountSiteID>
                  <RoundIncidentID>8</RoundIncidentID>
                  <RoundRoundAreaServiceScheduleID>157</RoundRoundAreaServiceScheduleID>
                  <RoundCode>REC1</RoundCode>
                  <ScheduleName>MonFort2</ScheduleName>
                  <ServiceName>Recycling Collection Service</ServiceName>
                  <RoundAreaName>REC1 - MonFort2</RoundAreaName>
                  <RoundIncidentDate>2019-04-08T16:12:10</RoundIncidentDate>
                  <RoundIncidentNotes>Road Closed</RoundIncidentNotes>
                  <RoundIncidentCreatedByID>129</RoundIncidentCreatedByID>
                  <RoundIncidentCreatedDate>2019-04-08T16:12:26.493</RoundIncidentCreatedDate>
               </RoundIncidents>
            </RoundIncidents>
         </GetSiteIncidentsResult>
      </GetSiteIncidentsResponse>
   </soap:Body>
</soap:Envelope>

XSLT 转换后的预期结果

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Body>
      <GetSiteIncidentsResponse xmlns="http://webservices.whitespacews.com/">
         <GetSiteIncidentsResult>
            <ErrorCode>0</ErrorCode>
            <ErrorDescription>Success</ErrorDescription>
            <SuccessFlag>true</SuccessFlag>            
               <RoundIncidents>
                  <ExtensionData />
                  <AccountSiteID>0</AccountSiteID>
                  <RoundIncidentID>8</RoundIncidentID>
                  <RoundRoundAreaServiceScheduleID>157</RoundRoundAreaServiceScheduleID>
                  <RoundCode>REC1</RoundCode>
                  <ScheduleName>MonFort2</ScheduleName>
                  <ServiceName>Recycling Collection Service</ServiceName>
                  <RoundAreaName>REC1 - MonFort2</RoundAreaName>
                  <RoundIncidentDate>2019-04-08T16:12:10</RoundIncidentDate>
                  <RoundIncidentNotes>Road Closed</RoundIncidentNotes>
                  <RoundIncidentCreatedByID>129</RoundIncidentCreatedByID>
                  <RoundIncidentCreatedDate>2019-04-08T16:12:26.493</RoundIncidentCreatedDate>
               </RoundIncidents>            
         </GetSiteIncidentsResult>
      </GetSiteIncidentsResponse>
   </soap:Body>
</soap:Envelope>

删除子项

将模板添加到标识转换中,该模板与子元素匹配,其中父项和子项具有相同的 QName,并且绕过了子项:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="*[name() = name(..)]">
    <xsl:apply-templates select="node()"/>
  </xsl:template>
</xsl:stylesheet>

Martin Honnen 方便的 XSLT 小提琴上的演示。

请注意,上面的内容在

词法上比较了 QNames,其中可能包含命名空间前缀。 若要正确(语义上(比较名称,请检查命名空间 URI:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="*[    local-name() = local-name(..) 
                         and namespace-uri() = namespace-uri(..)]">
    <xsl:apply-templates select="node()"/>
  </xsl:template>
</xsl:stylesheet>

更新了演示。


删除父级

根据 OP 的更新请求,下面介绍了在存在名为相同的子元素时删除父元素的方法。 在选择采用哪种方法时,请考虑通常一个孩子只能有一个父母,但父母可以有多个孩子。

简单的QName检查:

<xsl:template match="*[*[name() = name(..)]]">
  <xsl:apply-templates select="node()"/>
</xsl:template>

完整命名空间 URI 检查:

<xsl:template match="*[*[    local-name() = local-name(..) 
                         and namespace-uri() = namespace-uri(..)]]">
  <xsl:apply-templates select="node()"/>
</xsl:template>

信用:感谢@Alejandro和@michael.hor257k的有益更正和改进。

最新更新