Reputation: 9
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!
Upvotes: 0
Views: 539
Reputation:
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>
Upvotes: 1
Reputation: 176159
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>
Upvotes: 0