【问题标题】:Using xslt to parse and then format names使用 xslt 解析然后格式化名称
【发布时间】:2012-12-21 03:18:43
【问题描述】:

我正在尝试编写一个 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., & Agbayani, R. F.

对于只有 2 个作者的记录:

<names>
 <author>Lio-Po, Gilda D.</author>
 <author>Primavera, Jurgenne H.</author>
</names>

期望的输出是:Lio-Po, G. D., & 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>&amp; </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, & Agbayani,回复

【问题讨论】:

  • 如果我可以问,我们可以看看你尝试过的代码
  • @Satya,我现在用我尝试过的代码更新了我的帖子。
  • 您的代码中似乎遗漏了一些东西;您有两个模板,后跟一个 for-each 作为兄弟。
  • euler,我认为您的需求没有以清晰明确的方式描述-这是您仍然没有所需解决方案的主要原因-也许您仍然没有有(明确定义的)问题? ...
  • @C.M.Sperberg-McQueen,对不起,我是 stackoverflow 的新手,我很难放置代码,因为这是我的第一篇文章。我现在已经编辑了代码,这两个模板实际上是在 for-each 之后。

标签: xml substring xslt-1.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>&amp; </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.,     

如果你能忍受最后一个额外的逗号;)

追加: 这是我测试过的完整的 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);
    }

}

【讨论】:

  • 我在尝试您的代码时收到 java.lang.ClassNotFoundException: http:..exslt.org.strings..
  • 我附上了完整的 java 代码,请尝试并给我反馈。因为我已经成功运行了。
  • Mostafa,非常感谢你的努力,但很遗憾地告诉你,我只是 xsl 的新手,我对 java 不是很熟悉,不想告诉你这个但是老实说,我不知道如何处理您附加的 java 代码。关于我想要的输出,我想用一个空格分隔首字母(例如 Cruz, E.R. 到 Cruz, E. R.)
  • :) 不客气,欧拉,没问题的朋友。告诉我你的 xslt 处理器是什么?不是java内置处理器吗?
  • 设法通过将多余的逗号放在变量中来删除它。 &lt;xsl:value-of select="substring($citation-authors, 1, (string-length($citation-authors) - 2))"/&gt; 因为我注意到您的输出末尾包含 2 个额外字符,一个逗号和一个空格。
【解决方案2】:

我想我明白了!

<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>&amp; </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.

【讨论】:

  • 非常感谢 mostafa.s.mirzaee 的代码,我使用它的某些部分来实现我想要的输出。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
相关资源
最近更新 更多