Subject: Re: Adding an element to a list of similar elements?
From: "Jim Earley" <xml.jim@xxxxxxxxx>
Date: Sat, 5 Apr 2008 00:13:35 -0600
|
Dan,
You could try something like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="to_add" select="''"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/cruisecontrol/project.fullbuild">
<xsl:copy>
<xsl:copy-of select="node() | @*"/>
</xsl:copy>
<xsl:if test="not(following-sibling::project.fullbuild)">
<project.fullbuild name="{$to_add}" buildAfterFailed="false"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Cheers,
Jim Earley
On Fri, Apr 4, 2008 at 10:07 PM, Dan Stromberg
<dstromberglists@xxxxxxxxx> wrote:
>
> This feels incredibly simple - the sort of thing that should be in 62
> different web-based XSLT tutorials, but I've been googling for quite a while
> now, and I don't see much (anything) on the topic. This is about my 5th
> XSLT script, so I'm more than a bit of a newb.
>
> All I want to do is add an element to an xml document after a bunch of
> similar elements - hopefully with just one attribute changed relative to the
> similar line before it, or with a skeletal element if there isn't a similar
> element already in the file. I'm willing to do xpath queries to list what's
> in the file now, and run one or another XSLT script depending on what kind
> of change is needed, using some other language like bash or python to
> control which XSLT kicks in.
>
> I'm starting to feel like I should ignore XSLT and use a DOM-based Python
> script, but hopefully this list can save me from that (mostly because I
> believe it'd toast the comments, and I like comments :) .
>
> I have a basic XML document I'm testing with (it comes from cruisecontrol, a
> java-based automated build system) :
>
> <?xml version="1.0"?>
> <cruisecontrol>
> <project.mergeanddelete.dist name="db" buildAfterFailed="false"/>
> <project.mergeanddelete.dist name="DScripts" buildAfterFailed="false">
> <property name="log.mergedir" value="checkout/DScripts/dist"/>
> </project.mergeanddelete.dist>
> <project.fullbuild name="3.1.2-dev" buildAfterFailed="false"/>
> <project.fullbuild name="3.1.3-dev" buildAfterFailed="false"/>
> </cruisecontrol>
>
> And I just want to add <project.fullbuild name="3.1.4-ga"
> buildAfterFailed="false"/> after <project.fullbuild name="3.1.3-dev"
> buildAfterFailed="false"/> ideally using the 3.1.3-dev line as a template
> for the new 3.1.4 line.
>
> I experimented a bunch on my own with matching the last() project.fullbuild
> and trying to output two elements on it instead of one, but that seems to be
> going nowhere despite too many variations and machinations to count (you
> don't want to see all the things I tried - too much for the list). Is this
> at all a reasonable approach in standard XSLT? After more googling, I saw
> something saying that you shouldn't try to add attributes after a child, and
> I'm not sure if I was running afoul of that or not. I just kept getting the
> last() element nicely, and then a new element with empty attributes - not
> much in the way of a helpful error message, not even with --verbose.
>
> Here's -one- of the many things I tried based on this approach:
>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> <xsl:template match="node() | @*">
> <xsl:copy>
> <xsl:apply-templates select="node() | @*" />
> </xsl:copy>
> </xsl:template>
> <xsl:template match="/cruisecontrol/project.fullbuild[last()]">
> <xsl:copy>
> <xsl:copy-of select="node() | @*"/>
> </xsl:copy>
> <xsl:text>
 </xsl:text>
> <xsl:element name="project.fullbuild">
> <xsl:attribute name="name" value="${to_add}"/>
> </xsl:element>
> </xsl:template>
> </xsl:stylesheet>
>
> That {$to_add} is coming from a --string-param on the command line - but I'm
> not even getting a proper name attribute - it comes out a null string.
>
> I'm using xsltproc on an openSUSE 10.3 system:
>
> $ links -dump /tmp/t.html | sed '/^ *$/d'
> XSL version: 1.0
> Vendor: libxslt
> Vendor URL: http://xmlsoft.org/XSLT/
> Product name: [Undefined]
> Product version: [Undefined]
> Is schema-aware: [Undefined]
> Supports serialization: [Undefined]
> Supports backwards compatibility: [Undefined]
>
> $ xsltproc --version
> Using libxml 20630, libxslt 10120 and libexslt 813
> xsltproc was compiled against libxml 20630, libxslt 10120 and libexslt 813
> libxslt 10120 was compiled against libxml 20630
> libexslt 813 was compiled against libxml 20630
>
> Help me, Obi-Wan Kenobi... :)
>
> TIA!
|