[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: xsl with dynamic xpath statement from param and v
At 2007-09-06 11:38 +1200, Ralph Price wrote:
My problem seems like it should be simple There are a number of aspects of poor form that you should change. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:param name="argDictItem">RT.VAL.CANCELDATE</xsl:param> <xsl:variable name="sgl_qte">%27</xsl:variable> This method of escaping text is not supported in XML. That does not represent a single quote. <xsl:variable name="xpathDictItem" select="concat('group/dict[@id=',$sgl_qte,$argDictItem,$sgl_qte,']/val') "/> XSLT, as standardized, does not support dynamic evaluation of XPath syntax from a string as you have composed above. Some vendors offer such an extension but extensions are not portable. <xsl:template match="/"> <xsl:comment> $xpathDictItem = <xsl:value-of select="$xpathDictItem"/> </xsl:comment> <xsl:copy> <xsl:apply-templates select="node()"/> </xsl:copy> You don't need to copy the root node, it is implicitly in the result. </xsl:template> <xsl:template match="node()"> This template rule matches elements, comments, processing instructions and text nodes. <xsl:if test="name()!='item'"> <!-- carry on copying nodes --> <xsl:copy> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:if> <xsl:if test="name()='item'"> The above can be replaced with two template matches. The use of name()='item' is poor form and when you work with namespaces it will fail. <!-- copy item node only if the argDictItem does not have a value --> <xsl:choose> <xsl:when test="not($xpathDictItem)"> This does not evaluate the XPath syntax ... this is just checking the string for being empty ... the string is never empty so this is will never be triggered. <xsl:comment> node discarded - variable value used </xsl:comment> </xsl:when> <xsl:when test="group/dict[@id='RT.VAL.CANCELDATE']/val"> This is where the change can be made. <xsl:comment> node discarded - hardcoded value used </xsl:comment> </xsl:when> <xsl:otherwise> <xsl:copy> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:template> </xsl:stylesheet> ... However I wish to be able to delete the <item> elements based on the argDictItem parameter rather than my hardcoded value. In XSLT 1.0 a template rule cannot include a variable reference, while in XSLT 2.0 it can. I've written two solutions since the XSLT 2 is more elegant with the template matches. And are you sure you wanted to wipe out your source attributes in your target? I assumed this was an oversight, so I'm preserving them. You can easily remove them. Any leads would be most appreciated. Two solutions are below. I hope this helps in many ways ... it would seem that you've been misdirected in your XSLT techniques. . . . . . . . . . Ken
T:\ftemp>type ralph.xsl <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:param name="argDictItem">RT.VAL.CANCELDATE</xsl:param> <xsl:template match="/"> <xsl:comment> $argDictItem = <xsl:value-of select="$argDictItem"/> </xsl:comment> <xsl:apply-templates select="node()"/> </xsl:template> <xsl:template match="*"> <!--preserve this element--> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> <xsl:template match="item"> <!-- copy item node only if the argDictItem does not have a value --> <xsl:choose> <xsl:when test="group/dict[@id=$argDictItem]/val"> <xsl:comment> node discarded - detected <xsl:value-of select="$argDictItem"/> with a val </xsl:comment> </xsl:when> <xsl:otherwise> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> T:\ftemp>call xslt ralph.xml ralph.xsl ralph.out T:\ftemp>type ralph.out <!-- $argDictItem = RT.VAL.CANCELDATE--><origenxml> <data> <!-- node discarded - detected RT.VAL.CANCELDATE with a val --> <item> <id>07011*810*06*</id> <obj>RT.VALUATION</obj> <group> <id>MAIN</id> <dict id="RT.VAL.ID.RAW"> <desc>valuation number</desc> <val>07011*810*06*</val> </dict> <dict id="RT.VAL.CANCELDATE"> <desc>cancel date</desc> </dict> </group> </item> </data> </origenxml> T:\ftemp>type ralph2.xsl <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:param name="argDictItem">RT.VAL.CANCELDATE</xsl:param> <xsl:template match="/"> <xsl:comment> $argDictItem = <xsl:value-of select="$argDictItem"/> </xsl:comment> <xsl:apply-templates select="node()"/> </xsl:template> <xsl:template match="*"> <!--preserve this element--> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> <xsl:template match="item[group/dict[@id=$argDictItem]/val]"> <xsl:comment> node discarded - detected <xsl:value-of select="$argDictItem"/> with a val </xsl:comment> </xsl:template> </xsl:stylesheet> T:\ftemp>call xslt2 ralph.xml ralph2.xsl ralph2.out <!-- $argDictItem = RT.VAL.CANCELDATE--><origenxml> <data> <!-- node discarded - detected RT.VAL.CANCELDATE with a val --> <item> <id>07011*810*06*</id> <obj>RT.VALUATION</obj> <group> <id>MAIN</id> <dict id="RT.VAL.ID.RAW"> <desc>valuation number</desc> <val>07011*810*06*</val> </dict> <dict id="RT.VAL.CANCELDATE"> <desc>cancel date</desc> </dict> </group> </item> </data> </origenxml>
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|