468,247 Members | 1,330 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,247 developers. It's quick & easy.

Preceding with partial string

I seem to have a problem using the preceding:: on substrings of the
value. I'll try to explain with an example:

Let's say I had a XML that look like:

<Root>
<Row>
<Cell Name="Street" Value="2nd Street" />
</Row>
<Row>
<Cell Name="Street" Value="Meadow Lane" />
</Row>
<Row>
<Cell Name="Street" Value="2nd Street" />
</Row>
<Row>
<Cell Name="Street" Value="2nd Street" />
</Row>
<Row>
<Cell Name="Street" Value="Meadow Lane" />
</Row>

</Root>

Let's say I want to find the distinct streets. This is straight
forward and may look something like:
<xsl:template match="Root">
<xsl:element name="root">
<xsl:for-each select="./Row[Cell[@Name = 'Street' and not(@Value =
preceding::Cell[@Name= 'Street']/@Value) ]]">

<xsl:variable name="UniqueStreet" select="./Cell[@Name='Street']/
@Value"/>

<xsl:element name="street">
<xsl:attribute name="name">
<xsl:value-of select="$UniqueStreet"/>
</xsl:attribute>

<!-- This is where I would reiterate through the list to get the
list of residents
that live on that block -->
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>

This returns what I expect:

<root>
<street name="2nd Street"/>
<street name="Meadow Lane"/>
</root>

But let's say the address contained street numbers, and I needed to
strip out the street numbers when trying to look for unique street
names.
<Root>
<Row>
<Cell Name="Address" Value="1345 2nd Street" />
</Row>
<Row>
<Cell Name="Address" Value="332 Meadow Lane" />
</Row>
<Row>
<Cell Name="Address" Value="333 2nd Street" />
</Row>
<Row>
<Cell Name="Address" Value="8534 2nd Street" />
</Row>
<Row>
<Cell Name="Address" Value="556 Meadow Lane" />
</Row>

</Root>

<xsl:template match="Root">
<xsl:element name="root">
<xsl:for-each select="./Row[Cell[@Name = 'Address' and
not(substring-after(@Value, ' ') = substring-
after(preceding::Cell[@Name= 'Address']/@Value, ' ')) ]]">

<xsl:variable name="UniqueStreet" select="substring-after(./
Cell[@Name='Address']/@Value, ' ')"/>

<xsl:element name="street">
<xsl:attribute name="name"><xsl:value-of select="$UniqueStreet"/
></xsl:attribute>
<!-- This is where I would reiterate through the list to get the
list of residents
that live on that block -->
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>

This yields the output:

<root>
<street name="2nd Street"/>
<street name="Meadow Lane"/>
<street name="Meadow Lane"/>
</root>

Can someone explain why that is happening and how I can fix it?
Jun 27 '08 #1
1 2279
rn******@gmail.com wrote:
<xsl:for-each select="./Row[Cell[@Name = 'Street' and not(@Value =
preceding::Cell[@Name= 'Street']/@Value) ]]">
<xsl:for-each select="./Row[Cell[@Name = 'Address' and
not(substring-after(@Value, ' ') = substring-
after(preceding::Cell[@Name= 'Address']/@Value, ' ')) ]]">
Can someone explain why that is happening and how I can fix it?
The first comparison compares two node-sets (one with the single
attribute @Value, one with all @Value attributes of preceding::Cell
elements).
The second comparison however compares the single @Value attribute to
the string result of substring-after applied to the node-set of @Value
attributes of preceding::Cell elements and that way you only compare to
one preceding attribute, not to all.

With XSLT 2.0 you could use

<xsl:for-each select="./Row[Cell[@Name = 'Address' and
not(substring-after(@Value, ' ') = preceding::Cell[@Name=
'Address']/@Value/substring-after(., ' ')) ]]">

to make sure you compare to a sequence and not a string value but that
solution does not exist in XSLT 1.0.

And XSLT 2.0 has other (easier) ways to identify distinct values, there
is the function distinct-values
http://www.w3.org/TR/xpath-functions...istinct-values and there is
xsl:for-each-group.
With XSLT 1.0 you need to use Muenchian grouping:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:key name="by-street"
match="Row"
use="substring-after(Cell[@Name = 'Address']/@Value, ' ')"/>

<xsl:template match="Root">
<root>
<xsl:for-each
select="Row[generate-id() = generate-id(key('by-street',
substring-after(Cell[@Name = 'Address']/@Value, ' '))[1])]">
<street>
<xsl:value-of select="substring-after(Cell[@Name =
'Address']/@Value, ' ')"/>
</street>
</xsl:for-each>
</root>
</xsl:template>

</xsl:stylesheet>
--

Martin Honnen
http://JavaScript.FAQTs.com/
Jun 27 '08 #2

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Sven | last post: by
16 posts views Thread by pawel.pabich | last post: by
2 posts views Thread by saengpole | last post: by
4 posts views Thread by Phil Barber | last post: by
reply views Thread by zattat | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.