Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > Selecting the first node of a Sorted Group

Reply
Thread Tools

Selecting the first node of a Sorted Group

 
 
IcedDante
Guest
Posts: n/a
 
      12-10-2006
Working with a sorted group, the inability to use following-sibling
(which uses Document Order) and convert an RTF (not avaible with the
Parser that we are using) hampered our ability to solve the following
problem. Consider the following set of Data:

<example>
<Credentials time="3">
<UserId>kiss</UserId>
</Credentials>
<Credentials time="1" break="true">
<UserId>bob</UserId>
</Credentials>
<Credentials time="6" break="true">
<UserId>my</UserId>
</Credentials>
<Credentials time="0">
<UserId>Look,</UserId>
</Credentials>
<Credentials time="2">
<UserId>can</UserId>
</Credentials>
<Credentials time="9">
<UserId>tookish</UserId>
</Credentials>
</example>

When sorted in ascending order, the data reads: "Look, bob can kiss my
tookish". For our requirements I am processing it as a descending set:
"tookish my kiss can bob Look,"

That is the first requirement. However, in the even that a node with
the property of "break" equal to "true" is found, processing should
halt (multiple nodes can have the break property, but we really only
care about the first one).
So the output should read: "tookish my"

I devised a solution by using the substring-before operator to select
the first break node's sorted position.

<xslaram name="breakPos">
<xsl:for-each select="example/Credentials">
<xsl:sort select="@time" order="descending" />
<xsl:call-template name="countSequence">
</xsl:call-template>
</xsl:for-each>
</xslaram>
<xslaram name="endElem">
<xsl:value-of select="substring-before($breakPos,'|')" />
</xslaram>

<xsl:template match="/">
<html>
<body>
<xsl:for-each select="example/Credentials">
<xsl:sort select="@time" order="descending" />
<xsl:if test="($endElem = '') or (position() &lt;= $endElem)">
<xsl:value-of select="UserId" /><br />
</xsl:if>
</xsl:for-each>
</body>
</html>
</xsl:template>

Yeah, this renders the html output:
tookish<br />
my<br />

but I felt like the "endElem" parameter derivation was kind of a hack.
Would there be a better solution- possibly using Meunchian grouping to
perform this fix?

 
Reply With Quote
 
 
 
 
IcedDante
Guest
Posts: n/a
 
      12-10-2006
Whoops... I forgot the countSequence template. It basically builds the
list of nodes that have break="true" based on their position in the
sorted tree, delimited by the '|' symbol:

<xsl:template name="countSequence">
<xsl:choose>
<xsl:when test="(@break = 'true')">
<xsl:value-of select="position()" /><xsl:text>|</xsl:text>
</xsl:when>
<xsltherwise></xsltherwise>
</xsl:choose>
</xsl:template>

On Dec 9, 9:34 pm, "IcedDante" <(E-Mail Removed)> wrote:
> Working with a sorted group, the inability to use following-sibling
> (which uses Document Order) and convert an RTF (not avaible with the
> Parser that we are using) hampered our ability to solve the following
> problem. Consider the following set of Data:
>
> <example>
> <Credentials time="3">
> <UserId>kiss</UserId>
> </Credentials>
> <Credentials time="1" break="true">
> <UserId>bob</UserId>
> </Credentials>
> <Credentials time="6" break="true">
> <UserId>my</UserId>
> </Credentials>
> <Credentials time="0">
> <UserId>Look,</UserId>
> </Credentials>
> <Credentials time="2">
> <UserId>can</UserId>
> </Credentials>
> <Credentials time="9">
> <UserId>tookish</UserId>
> </Credentials>
> </example>
>
> When sorted in ascending order, the data reads: "Look, bob can kiss my
> tookish". For our requirements I am processing it as a descending set:
> "tookish my kiss can bob Look,"
>
> That is the first requirement. However, in the even that a node with
> the property of "break" equal to "true" is found, processing should
> halt (multiple nodes can have the break property, but we really only
> care about the first one).
> So the output should read: "tookish my"
>
> I devised a solution by using the substring-before operator to select
> the first break node's sorted position.
>
> <xslaram name="breakPos">
> <xsl:for-each select="example/Credentials">
> <xsl:sort select="@time" order="descending" />
> <xsl:call-template name="countSequence">
> </xsl:call-template>
> </xsl:for-each>
> </xslaram>
> <xslaram name="endElem">
> <xsl:value-of select="substring-before($breakPos,'|')" />
> </xslaram>
>
> <xsl:template match="/">
> <html>
> <body>
> <xsl:for-each select="example/Credentials">
> <xsl:sort select="@time" order="descending" />
> <xsl:if test="($endElem = '') or (position() &lt;= $endElem)">
> <xsl:value-of select="UserId" /><br />
> </xsl:if>
> </xsl:for-each>
> </body>
> </html>
> </xsl:template>
>
> Yeah, this renders the html output:
> tookish<br />
> my<br />
>
> but I felt like the "endElem" parameter derivation was kind of a hack.
> Would there be a better solution- possibly using Meunchian grouping to
> perform this fix?


 
Reply With Quote
 
 
 
 
p.lepin@ctncorp.com
Guest
Posts: n/a
 
      12-11-2006

IcedDante wrote:
> Working with a sorted group, the inability to use
> following-sibling (which uses Document Order) and convert
> an RTF (not avaible with the Parser that we are using)


Mentioning what processor you're using would've been a good
idea, instead of mentioning just some of its limitations.

> hampered our ability to solve the following
> problem. Consider the following set of Data:


[XML]

> When sorted in ascending order, the data reads: "Look,
> bob can kiss my tookish". For our requirements I am
> processing it as a descending set: "tookish my kiss can
> bob Look,"
>
> That is the first requirement. However, in the even that
> a node with the property of "break" equal to "true" is
> found, processing should halt (multiple nodes can have
> the break property, but we really only care about the
> first one). So the output should read: "tookish my"


[partial solution reeking of imperative programming]

It would've been a better idea to post the entire
transformation instead of just parts of it.

> Yeah, this renders the html output:
> tookish<br />
> my<br />


> but I felt like the "endElem" parameter derivation was
> kind of a hack. Would there be a better solution-
> possibly using Meunchian grouping to perform this fix?


I've grown accustomed to XSLT 2.0, so I can't think of any
elegant 1.0 solution off the top of my head. The following
works:

<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<result>
<xsl:apply-templates select="example/Credentials">
<xsl:sort select="@time" order="descending"/>
</xsl:apply-templates>
</result>
</xsl:template>
<xsl:template match="Credentials"/>
<xsl:template
match=
"
Credentials
[
not
(
../Credentials
[@time>current()/@time][@break='true']
)
]
">
<xsl:value-of select="UserId"/><br/>
</xsl:template>
</xsl:stylesheet>

....but specifying the sorting order in two separate places
in two different formats is a bit ugly, too, of course.

With XSLT 2.0, a much more elegant solution is possible:

<xsl:stylesheet version="2.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()" mode="copy">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="sorted">
<xsl:apply-templates
select="example/Credentials" mode="copy">
<xsl:sort select="@time" order="descending"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:apply-templates select="$sorted/Credentials"/>
</xsl:template>
<xsl:template match="Credentials"/>
<xsl:template
match=
"
Credentials
[
not
(
preceding-sibling::Credentials[@break='true']
)
]
">
<xsl:value-of select="UserId"/><br/>
</xsl:template>
</xsl:stylesheet>

[Tested with Saxon-8B]

--
Pavel Lepin

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Extracting the first child node of a parent node ofuuzo1@yahoo.no XML 2 03-17-2008 12:31 PM
Gridview header sorted column dimmed after selecting it Tony Girgenti ASP .Net Datagrid Control 0 03-21-2007 12:46 PM
Gridview header sorted column dimmed after selecting it Tony Girgenti ASP .Net Web Controls 0 03-13-2007 11:03 PM
xsl variable $node/text() but $node can non-node-set help! Tjerk Wolterink XML 2 08-24-2006 03:28 AM
How to set the node indent property between the parent node and the leaf node viveknatani@gmail.com ASP .Net 0 02-13-2006 07:11 PM



Advertisments