[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Recursively adding elements to a string

Subject: Re: Recursively adding elements to a string
From: "Gibson, Nathan" <nathan.gibson@xxxxxxxxxxxxxx>
Date: Wed, 5 Jun 2013 23:33:22 +0000
Re:  Recursively adding elements to a string
Looks like I can do it by using <xsl:analyze-string> recursively, as follows.
(I haven't yet implemented different element names for different parts of the
name---currently all use the generic <name> element.)

<xsl:template match="/root/full">
        <persName>
            <xsl:call-template name="process-names">
                <xsl:with-param name="name" select="."/>
                <xsl:with-param name="count" select="1"/>
                <xsl:with-param name="all-name-parts"
select="/root/*[ends-with(name(), 'name')]"/>
            </xsl:call-template>
        </persName>
    </xsl:template>


    <xsl:template name="process-names">
        <xsl:param name="name"/>
        <xsl:param name="count"/>
        <xsl:param name="all-name-parts"/>
        <xsl:param name="name-part" select="$all-name-parts[$count]"/>
        <xsl:choose>
            <xsl:when test="$name-part">
                <xsl:analyze-string select="$name" regex="{$name-part}"
flags="i">
                    <xsl:matching-substring>
                        <xsl:element name="name"><xsl:value-of
select="substring($name, string-length(substring-before($name, $name-part)) +
1, string-length($name) - string-length(substring-before($name, $name-part)) -
string-length(substring-after($name, $name-part)))"/></xsl:element>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:call-template name="process-names">
                            <xsl:with-param name="name" select="."/>
                            <xsl:with-param name="count" select="$count +
1"/>
                            <xsl:with-param name="all-name-parts"
select="$all-name-parts"/>
                        </xsl:call-template>
                    </xsl:non-matching-substring>
                </xsl:analyze-string>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy-of select="."/>
            </xsl:otherwise>
        </xsl:choose>

The result is
<persName><name>Doe</name>, <name>John</name> <name>J.</name></persName>
    John
    Doe
    J.

On Jun 5, 2013, at 12:59 PM, "Gibson, Nathan" <nathan.gibson@xxxxxxxxxxxxxx>
wrote:

> Hi,
>
> I'm trying to put some names into TEI format using data that looks like
this.
>
> <root>
>    <full-name>Doe, John J.</full-name>
>    <given-name>John</given-name>
>    <family-name>Doe</family-name>
>    <middle-name>J.</middle-name>
> </root>
>
> I would like to transform it into something like this:
> <persName><surname>Doe</surname>, <forename>John</forename>
<addName>J.</addName></persName>
>
> In other words, the given, family, and middle name fields simply show where
the forename, surname, and addName tags should be placed within the full name.
(As I need to keep the order and formatting of the full name in the source,
which are not standardized, I cannot simply recompose the full name from the
name parts. I won't go into all the details, but trust me on that.)
>
> So I'm using a recursive template to try to do this, but it only keeps the
final element it processes. Here's the code:
>
> <xsl:template match="/root/full-name">
>        <persName>
>            <xsl:call-template name="process-names">
>                <xsl:with-param name="full-name" select="."/>
>                <xsl:with-param name="count" select="1"/>
>            </xsl:call-template>
>        </persName>
>    </xsl:template>
>
>
>    <xsl:template name="process-names">
>        <xsl:param name="full-name"/>
>        <xsl:param name="count"/>
>        <xsl:param name="name-part" select="following-sibling::*[$count]"/>
>        <xsl:choose>
>            <xsl:when test="contains(name($name-part), 'given')">
>                <xsl:call-template name="process-names">
>                    <xsl:with-param name="full-name">
>                        <xsl:copy-of select="substring-before($full-name,
$name-part)"/>
>                        <xsl:element name="forename">
>                            <xsl:value-of
select="following-sibling::*[$count]"/>
>                        </xsl:element>
>                        <xsl:copy-of select="substring-after($full-name,
$name-part)"/>
>                    </xsl:with-param>
>                    <xsl:with-param name="count" select="$count + 1"/>
>                </xsl:call-template>
>            </xsl:when>
>            <xsl:when test="contains(name($name-part), 'family')">
>                <xsl:call-template name="process-names">
>                        <xsl:with-param name="full-name">
>                            <xsl:copy-of select="substring-before($full-name,
$name-part)"/>
>                            <xsl:element name="surname">
>                                <xsl:value-of
select="following-sibling::*[$count]"/>
>                            </xsl:element>
>                            <xsl:copy-of select="substring-after($full-name,
$name-part)"/>
>                        </xsl:with-param>
>                        <xsl:with-param name="count" select="$count + 1"/>
>                    </xsl:call-template>
>            </xsl:when>
>            <xsl:when test="contains(name($name-part), 'middle')">
>                <xsl:call-template name="process-names">
>                    <xsl:with-param name="full-name">
>                        <xsl:copy-of select="substring-before($full-name,
$name-part)"/>
>                        <xsl:element name="addName">
>                            <xsl:value-of
select="following-sibling::*[$count]"/>
>                        </xsl:element>
>                        <xsl:copy-of select="substring-after($full-name,
$name-part)"/>
>                    </xsl:with-param>
>                    <xsl:with-param name="count" select="$count + 1"/>
>                </xsl:call-template>
>            </xsl:when>
>            <xsl:otherwise>
>                <xsl:copy-of select="$full-name"/>
>            </xsl:otherwise>
>        </xsl:choose>
>    </xsl:template>
> </xsl:stylesheet>
>
> And here's what it creates:
>
>    <persName>Doe, John <addName>J.</addName></persName>
>    John
>    Doe
>    J.
>
> As best I can tell from debugging, the substring-before function flattens
the sequence contained in $full-name into string that contains no elements,
thus removing <forename> and <surname>. So I figure I either need to use a
function that plays well with sequences or figure out a way for elements to be
parsed as strings. But I haven't come up with how to do either one of those.
Suggestions?
>
> I'm using XSL 2.0 and Saxon EE 9.4.0.6 with Oxygen 14.2.
>
> Thanks,
> Nathan

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.