Re: [xsl] Allowing whitespace to stop merge of adjacent nodes

Subject: Re: [xsl] Allowing whitespace to stop merge of adjacent nodes
From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx>
Date: Tue, 10 Oct 2006 17:05:00 +0530
Please see if this stylesheet would help you:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output method="xml" indent="yes"/>

<xsl:key name="x" match="offset/@*" use="local-name()" />

 <xsl:template match="node() | @*">
   <xsl:copy>
     <xsl:apply-templates select="node() | @*" />
   </xsl:copy>
 </xsl:template>

 <xsl:template match="offset[not(preceding-sibling::offset)]">
   <offset>
     <xsl:for-each select="//offset/@*[generate-id() =
generate-id(key('x', local-name())[1])]">
       <xsl:attribute name="{local-name()}">
         <xsl:value-of select="sum(//offset/@*[local-name() =
local-name(current())])" />
       </xsl:attribute>
     </xsl:for-each>
   </offset>
 </xsl:template>

<xsl:template match="offset" />

</xsl:stylesheet>

This when applied to XML:

<text>
 Hello<offset x="2" y="4" /><offset x="3" y="2" />World
</text>

Produces output:

<?xml version="1.0" encoding="UTF-8"?>
<text>
 Hello<offset x="5" y="6"/>World
</text>

On 10/10/06, Matt Sims <matt.sims@xxxxxxxx> wrote:
Hi,

I'm hoping that somebody here can help me.

I'm using the following stylesheet to merge adjacent nodes of a
particular type and sum their attributes:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:aston="http://www.aston.tv/schemas/Aston/Aston7";>

<xsl:output method="xml" indent="yes"/>

  <xsl:template match="node()">
      <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates select="node()[1]"/>
      </xsl:copy>
      <xsl:apply-templates select="following-sibling::node()[1]"/>
  </xsl:template>

  <xsl:template match="aston:offset[not(node())]">
      <xsl:param name="a" select="/.."/>
      <xsl:choose>
          <xsl:when test="following-sibling::node()[self::* or
normalize-space(.)][1]/self::aston:offset[not(node())]">
              <xsl:apply-templates
select="following-sibling::aston:offset[1]">
                  <xsl:with-param name="a" select="$a|@*"/>
              </xsl:apply-templates>
          </xsl:when>
          <xsl:otherwise>
              <offset xmlns="http://www.aston.tv/schemas/Aston/Aston7";
x="{sum($a[name()='x']|@x)}" y="{sum($a[name()='y']|@y)}"
z="{sum($a[name()='z']|@z)}" />
              <xsl:apply-templates select="following-sibling::node()[1]"/>
          </xsl:otherwise>
      </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

For example, running it on the following XML:

<text>
  Hello<offset x="2" y="4" /><offset x="3" y="2" />World
</text>

would result in:

<text>
  Hello<offset x="5" y="6" />World
</text>

My problem occurs if I have a whitespace character between the two
adjacent nodes, like so:

<text>
  Hello<offset x="2" y="4" /> <offset x="3" y="2" />World
</text>

In this case, I wouldn't expect the nodes to be merged as they're not
strictly adjacent (there's a whitespace node between them) - but they are!

Can anyone tell me what I'm doing wrong?

Thanks in advance,

Matt.


--
Regards,
Mukul Gandhi

Current Thread