
Question:
Now I have an XML file as below:
<DM Name="A DM"> <DV id="SQL:Select something from db" Name="DV 1"> <Sample aid="SQL:Select something from db" /> </DV> <DV id="SQL:Select something from db" Name="DV 2"> <Sample aid="SQL:Select something from db" name ="DC"> good </Sample> </DV> </DM>
I want to use an XSLT to transform it, there is a parameter in this tamplet to determine which DV should be transformed: if the parameter($dvIndex = 0), then just keep all the elements and attributes, just transform the attriform the attritributes with the value started with "SQL:", if ($dvindext > 0), just transform the specific DV,(remove other DV). Now I write the XSLT as below, but it miss the DM's attributes, I don't know how to copy DM's attributes. I donot know if there is better solution. XML File:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:user="urn:my-scripts" > <xsl:output method="xml" indent="yes"/> <msxsl:script language="C#" implements-prefix="user"> <![CDATA[ public string UpperCase(string value){ return value.ToUpper(); } ]]> </msxsl:script> <xsl:param name="dvIndex" select="2" /> <xsl:template match="DM" > <xsl:copy> <xsl:choose> <xsl:when test="$dvIndex > 0"> <xsl:apply-templates select="DV[$dvIndex]"/> </xsl:when> <xsl:otherwise> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:copy> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!--[starts-with(translate(substring(.,1,4),'SQL:','sql:'),'sql:')]--> <xsl:template match="@*[user:UpperCase(substring(.,1,4))='SQL:']"> <xsl:attribute name="{name()}"> <xsl:value-of select="'parsedSQL'"/> </xsl:attribute> </xsl:template> </xsl:stylesheet>
this question is also related to my question 2# (How to only convert an XML file's attribute using XSLT, and leave the other content?)
Thanks very much!
Solution:1
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:param name="dvIndex" select="2" /> <xsl:template match="DM" > <xsl:copy> <xsl:apply-templates select="@*|DV[$dvIndex]"/> </xsl:copy> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="@*[starts-with(translate(substring(.,1,4),'SQL:','sql:'),'sql:')]"> <xsl:attribute name="{name()}"> <xsl:value-of select="'parsedSQL'"/> </xsl:attribute> </xsl:template> </xsl:stylesheet>
Result:
<DM Name="A DM"> <DV id="parsedSQL" Name="DV 2"> <Sample aid="parsedSQL" name="DC"> good </Sample> </DV> </DM>
With param dvIndex
in 0
:
<DM Name="A DM"></DM>
Note: Avoid scripting: it's not standar, it'll force to load script engine every time is used.
EDIT: If you want to process every DV
when $dvIndex is 0, then this stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:param name="dvIndex" select="2" /> <xsl:template match="DM" > <xsl:copy> <xsl:apply-templates select="@*|DV[$dvIndex]|DV[not($dvIndex)]"/> </xsl:copy> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="@*[starts-with(translate(substring(.,1,4),'SQL:','sql:'),'sql:')]"> <xsl:attribute name="{name()}"> <xsl:value-of select="'parsedSQL'"/> </xsl:attribute> </xsl:template> </xsl:stylesheet>
With $dvIndex is 0, output:
<DM Name="A DM"> <DV id="parsedSQL" Name="DV 1"> <Sample aid="parsedSQL"></Sample> </DV> <DV id="parsedSQL" Name="DV 2"> <Sample aid="parsedSQL" name="DC"> good </Sample> </DV> </DM>
Solution:2
The following probably does what you need. Note the additional <xsl:apply-templates select="@*" />
to copy the attributes.
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:user="urn:my-scripts"> <xsl:output method="xml" indent="yes"/> <msxsl:script language="C#" implements-prefix="user"> <![CDATA[ public string UpperCase(string value){ return value.ToUpper(); } ]]> </msxsl:script> <xsl:param name="dvIndex" select="0" /> <xsl:template match="DM" > <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:choose> <xsl:when test="$dvIndex > 0"> <xsl:apply-templates select="DV[$dvIndex]"/> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="DV"/> </xsl:otherwise> </xsl:choose> </xsl:copy> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!--[starts-with(translate(substring(.,1,4),'SQL:','sql:'),'sql:')]--> <xsl:template match="@*[user:UpperCase(substring(.,1,4))='SQL:']"> <xsl:attribute name="{name()}"> <xsl:value-of select="'parsedSQL'"/> </xsl:attribute> </xsl:template> </xsl:stylesheet>
Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
EmoticonEmoticon