At 2007-09-06 11:38 +1200, Ralph Price wrote:
My problem seems like it should be simple
Essentially there are nodes in my xml that I wish to discard based on a
child value existing in that node. That value is to be supplied by a
param.
The original data looks like:
...
---------------------------------------------
I only wish to retain in the output from the xsl the item elements
where, in this case the <dict id="RT.VAL.CANCELDATE"> does not have a
<val> child.
So far the stylesheet looks like:
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[(_at_)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[(_at_)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.xml
<origenxml xmlns="">
<data>
<item>
<id>07011*810*00*</id>
<obj>RT.VALUATION</obj>
<group>
<id>MAIN</id>
<dict id="RT.VAL.ID.RAW">
<desc>valuation number</desc>
<val>07011*810*00*</val>
</dict>
<dict id="RT.VAL.CANCELDATE">
<desc>cancel date</desc>
<val>01 Jan 2006</val>
</dict>
</group>
</item>
<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 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[(_at_)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[(_at_)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>
--
Upcoming public training: XSLT/XSL-FO Sep 10, UBL/code lists Oct 1
World-wide corporate, govt. & user group XML, XSL and UBL training
RSS feeds: publicly-available developer resources and training
G. Ken Holman mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/
Box 266, Kars, Ontario CANADA K0A-2E0 +1(613)489-0999 (F:-0995)
Male Cancer Awareness Jul'07 http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers: http://www.CraneSoftwrights.com/legal
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--