patternMinor
Extracting the first two initials of a person's name
Viewed 0 times
persontheinitialstwofirstnameextracting
Problem
I've come up with a hackish approach to get my XSL function to only return the first 2 initials of a person. I think there should be a more efficient way to do this though. The
So 5 examples of my XML:
My function call:
and my inefficient XSL function:
So with the first two XML blocks the expected output/return is:
and
The remaining three should return (as expected, no
but I thought there would be a way to stop the iteration. For example my PHP just has:
replace specifically is what I think I should be able to get rid of, looking through docs though I can't figure out how to correctly iterate with the split.So 5 examples of my XML:
Test I
Chris
Test II
Chris Chris
Test III
Chris Eat Meat
Test IV
Chris-Eat Meat
Test V
Chris-Eat-Meat
My function call:
and my inefficient XSL function:
0]
return concat(substring($token,1,1),'.'),
''), '(\w\.\w?\.?).*', '$1')
"/>
So with the first two XML blocks the expected output/return is:
C.and
C. C.The remaining three should return (as expected, no
M. because we only want the first 2 initials)C. E.but I thought there would be a way to stop the iteration. For example my PHP just has:
$abbreviated_firstnames = array();
$firstnames = mb_split('(\s+|-)', html_entity_decode($this->firstname,ENT_QUOTES,'UTF-8'));
$intial_count = 0;
foreach ($firstnames as $firstname) {
$intial_count++;
$firstinit = mb_substr($firstname,0,1,'UTF-8');
if ($firstinit) {
$abbreviated_firstnames[] = $firstinit . '.';
if($intial_count >= 2) {
break; // <---- we got 2 matches stop NOW
}
}
}
return implode(' ',$abbreviated_firstnames);Solution
I think you should be able to get rid of the
You should also be able to remove the
You can also remove the
New function based on above suggestions:
Complete example (used Saxon-HE 9.5 to test)...
XML Input (Added test VI)
XSLT 2.0
XML Output
replace() by testing the position of the token in an additional predicate. You should also be able to remove the
string-join() (unless you don't want spaces between the initials).You can also remove the
string-length() test by adjusting the regex for -.New function based on above suggestions:
= position()]
return concat(substring($token,1,1),'.')
"/>
Complete example (used Saxon-HE 9.5 to test)...
XML Input (Added test VI)
Test I
Chris
Test II
Chris Chris
Test III
Chris Eat Meat
Test IV
Chris-Eat Meat
Test V
Chris-Eat-Meat
Test VI
Chris---Eat----Meat
XSLT 2.0
= position()]
return concat(substring($token,1,1),'.')
"/>
XML Output
Test I
Chris
C.
Test II
Chris Chris
C. C.
Test III
Chris Eat Meat
C. E.
Test IV
Chris-Eat Meat
C. E.
Test V
Chris-Eat-Meat
C. E.
Test V
Chris---Eat----Meat
C. E.
Code Snippets
<xsl:function name="pull_it:get_initials">
<xsl:param name="names"/>
<xsl:value-of select="
for $token in tokenize($names,'(-+|\s+)')[2 >= position()]
return concat(substring($token,1,1),'.')
"/>
</xsl:function><doc>
<name>
<surname>Test I</surname>
<given-names>Chris</given-names>
</name>
<name>
<surname>Test II</surname>
<given-names>Chris Chris</given-names>
</name>
<name>
<surname>Test III</surname>
<given-names>Chris Eat Meat</given-names>
</name>
<name>
<surname>Test IV</surname>
<given-names>Chris-Eat Meat</given-names>
</name>
<name>
<surname>Test V</surname>
<given-names>Chris-Eat-Meat</given-names>
</name>
<name>
<surname>Test VI</surname>
<given-names>Chris---Eat----Meat</given-names>
</name>
</doc><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:pull_it="pull_it"
exclude-result-prefixes="pull_it">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:function name="pull_it:get_initials">
<xsl:param name="names"/>
<xsl:value-of select="
for $token in tokenize($names,'(-+|\s+)')[2 >= position()]
return concat(substring($token,1,1),'.')
"/>
</xsl:function>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="name">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<initials><xsl:value-of select="pull_it:get_initials(given-names)"/></initials>
</xsl:copy>
</xsl:template>
</xsl:stylesheet><doc>
<name>
<surname>Test I</surname>
<given-names>Chris</given-names>
<initials>C.</initials>
</name>
<name>
<surname>Test II</surname>
<given-names>Chris Chris</given-names>
<initials>C. C.</initials>
</name>
<name>
<surname>Test III</surname>
<given-names>Chris Eat Meat</given-names>
<initials>C. E.</initials>
</name>
<name>
<surname>Test IV</surname>
<given-names>Chris-Eat Meat</given-names>
<initials>C. E.</initials>
</name>
<name>
<surname>Test V</surname>
<given-names>Chris-Eat-Meat</given-names>
<initials>C. E.</initials>
</name>
<name>
<surname>Test V</surname>
<given-names>Chris---Eat----Meat</given-names>
<initials>C. E.</initials>
</name>
</doc>Context
StackExchange Code Review Q#132647, answer score: 2
Revisions (0)
No revisions yet.