Reputation: 29
An XML response I am getting has the same named elements next to each other in the response which is causing me issues, I need to remove this recurring element using XSLT 1.0. The element in question in the response is <RoundIncidents>
. I have had a look through other questions but can't find what I need to transform the response to the correct format.
<?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>
<?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>
Upvotes: 1
Views: 207
Reputation: 111686
Add a template to the identity transform that matches child elements where the parent and child have the same QName, and the child is bypassed:
<?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>
Demo on Martin Honnen's handy XSLT Fiddle.
Note that the above lexically compares QNames, which may include namespace prefixes. To compare names properly (semantically), check the namespace URIs:
<?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>
Updated demo.
Per OP's updated request, here's how to remove the parent element when there's a child element named the same. In choosing which approach to take, consider that in general a child can only have one parent, but a parent can have multiple children.
Simple QName check:
<xsl:template match="*[*[name() = name(..)]]">
<xsl:apply-templates select="node()"/>
</xsl:template>
Full Namespace URI check:
<xsl:template match="*[*[ local-name() = local-name(..)
and namespace-uri() = namespace-uri(..)]]">
<xsl:apply-templates select="node()"/>
</xsl:template>
Credit: Thanks to @Alejandro and @michael.hor257k for helpful corrections and improvements.
Upvotes: 3