Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old March 9th, 2006, 10:27 AM
Authorized User
 
Join Date: Mar 2004
Posts: 20
Thanks: 0
Thanked 0 Times in 0 Posts
Default following-sibling assistance needed

Hello,

I have searched the forums and can't seem to find a fix for my need yet. I am stepping through an XML document and trying to pull the content (text) of two siblings together into one.

First the data:
Code:
<Body>
    <Para>ARTICLE 1</Para>
    <Para>BILL OF RIGHTS</Para>
    <otherNode>other text</otherNode> . . .
I am creating a single element node with the text of the Para's concatenated and centered. So I want my output to be like this:

     <Para Justify="Center">ARTICLE 1 BILL OF RIGHTS</Para>

I match on the first Para, start building my element, and then bring in the text. Here's my attempt:
Code:
<xsl:template match="Para">
    <xsl:element name="Para">
        <xsl:attribute name="Justify" select="'Center'"/>
        <xsl:value-of select="."/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="following-sibling::*[1]" />
    </xsl:element>
</xsl:template>
I receive an error on the following-sibling line above, the error is "Error in XPath 2.0 expression (Not a node item)". I have tried multiple efforts based on tips from this forum, including 'following-sibling::Para[1]' and 'following-sibling::*[position()=1]' and even 'Para[1]/text()' all to no avail.

Are there any suggestions? I'd like to think I'm at least 'close'. Thank you in advance for any and all assistance.

Dan



 
Old March 9th, 2006, 11:51 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Your code looks fine to me, what XSLT 2.0 processor are you using?



Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old March 9th, 2006, 02:08 PM
Authorized User
 
Join Date: Mar 2004
Posts: 20
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thank you for replying, Michael. And you are correct, in that it does work.

In my effort to be brief in my example, I left out part of the template that appears to be extremely relevant. I am creating this element as a result of mathing a regular expression string. So the prior code should have shown that it was nested within an <analyze-string> rule. The full code was thus:
Code:
    <xsl:template match="Para">
        <xsl:analyze-string select="text()" regex="(ARTICLE) (\d+)">
            <xsl:matching-substring>
                <xsl:element name="Para">
                    <xsl:attribute name="Justify" select="'Center'" />
                    <xsl:value-of select="."/>
                    <xsl:text> </xsl:text>
                    <xsl:value-of select="following-sibling::*[1]"/>
                </xsl:element>
            </xsl:matching-substring>
            <xsl:non-matching-substring /> 
        </xsl:analyze-string>
    </xsl:template>
I have remedied by building my new heading line into a variable outside of the <analyze-string> block and then referencing the variable when needed.
Code:
    <xsl:template match="Para">
        <xsl:variable name="artHeading" select="concat(text(), ' ', following-sibling::*[1])" />
        <xsl:analyze-string select="text()" regex="(ARTICLE) (\d+)">
            <xsl:matching-substring>
                <xsl:element name="Para">
                    <xsl:attribute name="Justify" select="'Center'" />
                    <xsl:value-of select="$artHeading"/>   
                </xsl:element>
            </xsl:matching-substring>
            <xsl:non-matching-substring />    
        </xsl:analyze-string>
    </xsl:template>
I am still puzzled why the following-sibling axis did not work within the <analyze-string> element.

Is there a cleaner way to achieve what I am trying to achieve?


Regards,
Dan


 
Old March 9th, 2006, 02:54 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Yes, this difference is highly relevant. xsl:analyze-string changes the context item, and any axis expression (following-sibling included) starts from the context item, which must be a node.

the solution is

<xsl:variable name="x" select="."/>

outside the xsl:analyze-string, and

$x/following-sibling::*

inside it.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ Assistance KramRJ C++ Programming 2 May 19th, 2007 07:24 AM
Assistance with function mat41 Classic ASP Professional 3 August 11th, 2006 12:01 PM
Network Assistance DuncanFinney C# 6 August 1st, 2005 06:42 PM
Project Assistance PetraMan Javascript How-To 5 April 7th, 2005 10:58 PM
MDI Sibling calling Sibling... Nick.Net VB.NET 2002/2003 Basics 1 December 8th, 2003 09:23 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.