我正在尝试编写一个XSLT样式表来处理作者的名字并创建引用的APA版本。关于作者姓名的APA引用格式:名称列出姓氏,然后是姓名首字母,如果姓名是引文的第一个元素。使用逗号分隔名称,并在最后一位作者之前使用&符号(&)。我在这篇文章中遵循了Dimitre Novatchev的解决方案:Using XSLT to select after EACH instance in a string/substring但我没有得到我想要的结果。
输入:
<names>
<author>Lio-Po, Gilda D.</author>
<author>Primavera, Jurgenne H.</author>
<author>Cuvin-Aralar, Ma. Lourdes A.</author>
<author>Cruz, E.R.</author>
<author>Catacutan, M.R.</author>
<author>Agbayani, R.F.</author>
</names>
期望的输出将是: Lio-Po,G.D.,Primavera,J.H.,Cuvin-Aralar,M.L.A.,Cruz,E.R.,Catacutan,M.R。,&amp; Agbayani,R。F。
仅有2位作者的记录:
<names>
<author>Lio-Po, Gilda D.</author>
<author>Primavera, Jurgenne H.</author>
</names>
期望的输出将是: Lio-Po,G.D。,&amp; Primavera,J。H。
提前致谢。下面是我的代码,其代码来自Dimitre的。
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select="/names/author">
<xsl:choose>
<xsl:when test="count(following-sibling::text()) = 1">
<xsl:text>& </xsl:text>
<xsl:apply-templates/>
</xsl:when>
<xsl:when test="count(following-sibling::text()) != 0">
<xsl:apply-templates/>
<xsl:text>, </xsl:text>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="substring-before(., ',')"/>
<xsl:call-template name="replaceTokenDelims">
<xsl:with-param name="pStr" select="concat(normalize-space(substring-after(., ',')), ' ')"/>
<xsl:with-param name="pToken" select="' '"/>
<xsl:with-param name="pReplacement" select="', '"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="replaceTokenDelims">
<xsl:param name="pStr"/>
<xsl:param name="pToken"/>
<xsl:param name="pReplacement"/>
<xsl:if test="$pStr">
<xsl:value-of select="$pReplacement"/>
<xsl:value-of select="substring(substring-before($pStr, $pToken),1,1)"/>
<xsl:call-template name="replaceTokenDelims">
<xsl:with-param name="pStr" select="substring-after($pStr, $pToken)"/>
<xsl:with-param name="pToken" select="$pToken"/>
<xsl:with-param name="pReplacement" select="$pReplacement"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
运行上面的代码给出了输出: Lio-Po,G,D,Primavera,J,H,Cuvin-Aralar,M,L,A,Cruz,E,Catacutan,M,&amp; Agbayani,R
答案 0 :(得分:1)
<强>已更新强>
这个有效,我甚至自己测试过:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each select="/names/author">
<xsl:if test="position() = last()">
<xsl:text>& </xsl:text>
</xsl:if>
<xsl:for-each select="str:tokenize(.,' ')">
<xsl:choose>
<xsl:when test="position() = 1">
<xsl:value-of select="."></xsl:value-of>
</xsl:when>
<xsl:when test="substring(.,2,1) = '.'">
<xsl:for-each select="str:tokenize(.,'.')">
<xsl:value-of select="concat(.,'.')"></xsl:value-of>
<xsl:if test="position() != last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(substring(.,1,1),'.')"></xsl:value-of>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="position() = last()">
<xsl:text>, </xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
您给定XML的输出将是:
Lio-Po, G. D., Primavera, J. H., Cuvin-Aralar, M. L. A., Cruz, E. R., Catacutan, M. R., & Agbayani, R. F.,
如果你能忍受最后一个额外的逗号;)
<强> APPEND:强> 这是我测试过的完整的java代码,看起来还不错。
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.transform.TransformerException;
public class XLSTTester {
public static void main(String[] params){
try {
transform("d:\\workspace1\\test.xml","d:\\workspace1\\test.xsl");
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void transform(String xmlFileFullPath, String xsltFileFullPath) throws TransformerException, IOException{
File xmlFile = new File(xmlFileFullPath);
File xsltFile = new File(xsltFileFullPath);
StringWriter sw = new StringWriter();
javax.xml.transform.Source xmlSource = new javax.xml.transform.stream.StreamSource(xmlFile);
javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(xsltFile);
javax.xml.transform.Result transResult = new javax.xml.transform.stream.StreamResult(sw);
// create an instance of TransformerFactory
javax.xml.transform.TransformerFactory transFact = javax.xml.transform.TransformerFactory.newInstance( );
javax.xml.transform.Transformer trans = transFact.newTransformer(xsltSource);
trans.transform(xmlSource, transResult);
}
}
答案 1 :(得分:0)
我想我明白了!
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:for-each select="/names/author">
<xsl:variable name="firstname">
<xsl:value-of select="substring-after(., ', ')"/>
</xsl:variable>
<xsl:if test="position() = last() and position() != 1">
<xsl:text>& </xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="substring($firstname,2,1) = '.'">
<xsl:value-of select="concat(str:tokenize(.,','), ', ')"/>
<xsl:for-each select="str:tokenize($firstname,'.')">
<xsl:value-of select="concat(.,'.')"/>
<xsl:if test="position() != last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(str:tokenize(.,','), ', ')"/>
<xsl:for-each select="str:tokenize($firstname,' ')">
<xsl:value-of select="concat(substring(.,1,1),'.')"/>
<xsl:if test="position() != last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
如果使用以下输入进行测试:
<names>
<author>Lio-Po, Gilda D.</author>
<author>Cuvin-Aralar, Ma. Lourdes A.</author>
<author>De la Cruz, Juan C.</author>
<author>Cruz, E.R.</author>
<author>Catacutan, M.R.</author>
<author>De los Santos, M.A.</author>
<author>Primavera, Jurgenne H.</author>
</names>
产生了所需的结果:
Lio-Po, G. D., Cuvin-Aralar, M. L. A., De la Cruz, J. C., Cruz, E. R., Catacutan, M. R., De los Santos, M. A., & Primavera, J. H.