Subject: Re: [xsl] Recursively adding elements to a string From: "Gibson, Nathan" <nathan.gibson@xxxxxxxxxxxxxx> Date: Wed, 5 Jun 2013 23:33:22 +0000 |
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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Recursively adding elements t, Gibson, Nathan | Thread | [xsl] German umlaut sort, Jean-Pierre Lamon |
[xsl] Balisage 2013: Call for Late-, Tommie Usdin | Date | [no subject], Unknown |
Month |