xsl-list
[Top] [All Lists]

Re: [xsl] Adding an element to a list of similar elements?

2008-04-04 23:14:05
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(_at_)gmail(_dot_)com> 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>&#xA;    </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!


--~------------------------------------------------------------------
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>
--~--



--~------------------------------------------------------------------
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>
--~--

<Prev in Thread] Current Thread [Next in Thread>