Reputation: 151
I am new to XML and XSL. I have got a requirement write an XSL script to replace the greater than (>) and less than (<) sign of some child elements with the escape strings. I need to perform the replace on the child elements within the "startupXml" element (see code below)
<?xml version="1.0" encoding="utf-8" ?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Startup2 xmlns="http://keyfax.touch-base.com/">
<startupXml>
<KeyfaxData>
<Startup>
<Config>Test</Config>
<Mode>RD</Mode>
<UserName>JBLOG</UserName>
<PropertyType>P</PropertyType>
<PropertyID>L0000</PropertyID>
<ReferenceID>12345</ReferenceID>
<Property>
<ContactHistory/>
</Property>
</Startup>
</KeyfaxData>
</startupXml>
</Startup2>
</s:Body>
</s:Envelope>
The result should look like this:
<?xml version="1.0" encoding="utf-8" ?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Startup2 xmlns="http://keyfax.touch-base.com/">
<startupXml>
<KeyfaxData>
<Startup>
<Config>Test</Config>
<Mode>RD</Mode>
<UserName>JBLOG</UserName>
<PropertyType>P</PropertyType>
<PropertyID>L0000</PropertyID>
<ReferenceID>12345</ReferenceID>
<Property>
<ContactHistory/>
</Property>
>/Startup<
>/KeyfaxData<
</startupXml>
</Startup2>
</s:Body>
</s:Envelope>
I've tried some xsl scripts to find and replace, but as I am new to XML and XSL, the outcome was not successful. Could someone point me in the correct direction please.
Thanks in advance.
Upvotes: 1
Views: 5263
Reputation: 22617
In this general case (escaping all descendant elements of a particular input element), you could use
XSLT Stylesheet (online)
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:kf="http://keyfax.touch-base.com/">
<xsl:output method="xml" omit-xml-declaration="no" encoding="UTF-8" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="kf:startupXml//*">
<xsl:value-of select="concat('<',name(),'>')"/>
<xsl:apply-templates/>
<xsl:value-of select="concat('</',name(),'>')"/>
</xsl:template>
</xsl:transform>
XML Output
Your expected output immediately closes the ContactHistory
element: <Contact History/>
, but that would require additional logic.
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Startup2 xmlns="http://keyfax.touch-base.com/">
<startupXml>
<KeyfaxData>
<Startup>
<Config>Test</Config>
<Mode>RD</Mode>
<UserName>JBLOG</UserName>
<PropertyType>P</PropertyType>
<PropertyID>L0000</PropertyID>
<ReferenceID>12345</ReferenceID>
<Property>
<ContactHistory></ContactHistory>
</Property>
</Startup>
</KeyfaxData>
</startupXml>
</Startup2>
</s:Body>
</s:Envelope>
Upvotes: 3
Reputation: 163352
The main thing you need to bear in mind is that XSLT doesn't see the markup, it sees the tree of nodes formed by parsing the markup. So you need a template rule something like this:
<xsl:template match="*" mode="escape-markup">
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
<xsl:apply-templates mode="#current"/>
<xsl:text></</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:template>
which you then invoke when you hit the relevant element:
<xsl:template match="startUpXml">
<xsl:apply-templates mode="escape-markup"/>
</xsl:template>
It gets a little more complicated if you have to handle attributes and namespaces.
Upvotes: 1