Reputation: 211
I am trying to find a way to add an element to input xml file via XSLT only if it doesn't already exist. My solution below works in cases where the element doesn't exist, however if it DOES exist (I still need to put the value for sessionId), it still creates a new one.
XSL:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="xsl exsl xs">
<xsl:output method="xml" version="1.0" indent="yes" encoding="utf-8" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="//*[local-name() = 'SessionHeader']">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:choose>
<xsl:when test="not(sessionId)">
<sessionId><xsl:value-of select="9876543210"/></sessionId>
</xsl:when>
<xsl:otherwise>
<xsl:copy><xsl:value-of select="9876543210"/></xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Sample XML:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<SessionHeader>
<sessionId />
</SessionHeader>
</soap:Header>
<soap:Body>
....
</soap:Body>
</soap:Envelope>
After 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:Header>
<SessionHeader>
<sessionId />
<sessionId xmlns="">9876543210</sessionId>
</SessionHeader>
</soap:Header>
<soap:Body>
....
</soap:Body>
</soap:Envelope>
Note the 2 sessionId elements
Again, if the sessionId element doesn't exist at all, it works fine. Thanks in advance for any useful help.
Upvotes: 1
Views: 3258
Reputation: 101652
If you can safely assume that sessionId
will always be the only child of SessionHeader
, then here is an easy way to accomplish this:
<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:strip-space elements="*"/>
<!-- identity template -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SessionHeader[not(normalize-space(sessionId))]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<sessionId>9876543210</sessionId>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If SessionHeader
has no sessionId
or an empty/all whitespace sessionId
, it simply creates one with the predefined value. If it does already contain a sessionId
with a value, then the identity template takes care of copying it.
Upvotes: 0
Reputation: 116957
I think (or rather guess) you want to do something like:
XSLT 1.0
<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:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SessionHeader[not(sessionId)]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<sessionId><xsl:value-of select="9876543210"/></sessionId>
</xsl:copy>
</xsl:template>
<xsl:template match="sessionId[not(text())]">
<xsl:copy>
<xsl:text>9876543210</xsl:text>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This adds the value "9876543210" to the sessionId
element if it's empty or creates a new sessionId
element with the above value if it doesn't exist. Otherwise the default identity transforn template will copy the existing sessionId
element, along with its existing value.
Upvotes: 1