Removing an element who's child element value is 0 through XSLT
I have an xml file which I need to transform with XSLT. In my XSLT file I'm doing a number of things with the xml file. I first copy all elements; then I rename some of the elements. Lastly I need to remove for output any dealer-code element
that has a dealer-code-name
of 0. The 1st 2 pieces I have working, but I've tried every piece of code I've found online and can't seem to remove those offending dealer-code
elements. I'm new to XSLT so I may be doing it all wrong; any help would be appreciated.
Partial xml code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="xmlstructure.xsl"?>
<AdBaseData>
<AdBasePreprintInfo FromDistribute="true">
<PreprintInsert>
<Sides>2</Sides>
<PageCount>2</PageCount>
<InsertSchedule>
<AdLocInfo>
<rundates>
<date>12042010</date>
</rundates>
</AdLocInfo>
<invoice-text>South Plaza - Stalker Advertisin</invoice-text>
<BillingOverride Type="Subscriber">49996</BillingOverride>
<deal-code0>
<dealer-code-name>A20</dealer-code-name>
<Delivery-Method Type="Subscriber">
<Selected>true</Selected>
</Delivery-Method>
</deal-code0>
<deal-code1>
<dealer-code-name>0</dealer-code-name>
<Delivery-Method Type="Subscriber">
<Selected>true</Selected>
</Delivery-Method>
</deal-code1>
</InsertSchedule>
</PreprintInsert>
My xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3开发者_如何学C.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(name(), 'deal-code')]">
<xsl:element name="dealer-code">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="dealer-code[@dealer-code-name='0']">
</xsl:template>
</xsl:stylesheet>
The rename of deal-code
to dealer-code
works. However, the last part to not output any dealer-code-name
with a value of 0 does not. My resulting xml file still lists every dealer-code
element.
This input:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="xmlstructure.xsl"?>
<AdBaseData>
<AdBasePreprintInfo FromDistribute="true">
<PreprintInsert>
<Sides>2</Sides>
<PageCount>2</PageCount>
<InsertSchedule>
<AdLocInfo>
<rundates>
<date>12042010</date>
</rundates>
</AdLocInfo>
<invoice-text>South Plaza - Stalker Advertisin</invoice-text>
<BillingOverride Type="Subscriber">49996</BillingOverride>
<deal-code0>
<dealer-code-name>A20</dealer-code-name>
<Delivery-Method Type="Subscriber">
<Selected>true</Selected>
</Delivery-Method>
</deal-code0>
<deal-code1>
<dealer-code-name>0</dealer-code-name>
<Delivery-Method Type="Subscriber">
<Selected>true</Selected>
</Delivery-Method>
</deal-code1>
</InsertSchedule>
</PreprintInsert>
</AdBasePreprintInfo>
</AdBaseData>
with this stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(name(), 'deal-code')][dealer-code-name = '0']"/>
</xsl:stylesheet>
produces the output you're wanting:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="xmlstructure.xsl"?><AdBaseData>
<AdBasePreprintInfo FromDistribute="true">
<PreprintInsert>
<Sides>2</Sides>
<PageCount>2</PageCount>
<InsertSchedule>
<AdLocInfo>
<rundates>
<date>12042010</date>
</rundates>
</AdLocInfo>
<invoice-text>South Plaza - Stalker Advertisin</invoice-text>
<BillingOverride Type="Subscriber">49996</BillingOverride>
<deal-code0>
<dealer-code-name>A20</dealer-code-name>
<Delivery-Method Type="Subscriber">
<Selected>true</Selected>
</Delivery-Method>
</deal-code0>
</InsertSchedule>
</PreprintInsert>
</AdBasePreprintInfo>
</AdBaseData>
You have two problems:
- You do not have any
dealer-code
elements in the source XML. They aredeal-code0
anddeal-code1
dealer-code-name
is an element, not an attribute.
Your XPATH currently matches dealer-code
elements with @dealer-code-name='0'
. Since there are no dealer-code
elements and there are no dealer-code-name
attributes, it never matches and does not suppress the content.
You need to adjust your XPATH to match the deal-code
elements similar to how you are in the other template and add an additional predicate filter for child elements dealer-code-name
with a value of 0. Additionally, since both of your templates have similar matching logic, they may get the same priority level. You may need to bump up the priority of this redaction template, so that it "wins" against the more generic match:
<xsl:template match="*[starts-with(name(), 'deal-code') and dealer-code-name='0']" priority="1"/>
<?xml version="1.0" encoding="UTF-8"?>
<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:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(name(), 'deal-code')]">
<xsl:if test="dealer-code-name!='0']">
<xsl:element name="dealer-code">
<xsl:apply-templates/>
</xsl:element>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
you have no element dealer-code
in your input xml, but you can filter when your processing elements starting with deal-code
by testing if they have a child element dealer-code-name
which value is 0
精彩评论