如何使用xsl和xml进行I18N

时间:2012-08-23 06:51:19

标签: xml xslt internationalization

我正在尝试使用xml / xsl以不同语言编写页面。我想只有一个xml和一个xsl。在我的页面上Url我有一个参数pLanguage,我想我可以用来查看我选择的是英语还是荷兰语。

我尝试使用此代码,但我不知道如何将它放在一起:

首先,我创建所有必须翻译的单词的变量:

<xsl:variable name="lang.pageTitle" select="'This is the title in English'"/>

要获取模板中的pageTitle,我现在可以使用

<xsl:value-of select="$lang.pageTitle"/>

我想用if-else语句替换上面的第一行代码来测试我选择的语言是EN还是NL这样:

<xsl:choose>
      <xsl:when test="$choosenLanguage &#61; ‘NL’">
        <xsl:variable name="lang.pageTitle" select="Titel in het nederlands'"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="lang.pageTitle" select="'This is the title in English'"/>
      </xsl:otherwise>
    </xsl:choose>

但我收到错误: java.lang.IllegalArgumentException:无法解析参数号$ lang.opdracht

2 个答案:

答案 0 :(得分:3)

以下是如何以通用方式完成此操作的完整示例

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pLang" select="'nl'"/>

 <my:texts>
  <pageTitle lang="en">This is the title in English</pageTitle>
  <pageTitle lang="nl">Titel in het nederlands</pageTitle>
 </my:texts>

 <xsl:variable name="vTexts" select="document('')/*/my:texts"/>

 <xsl:template match="/">
     <html>
      <title>
        <xsl:value-of select="$vTexts/pageTitle[@lang = $pLang]"/>
      </title>
     </html>
 </xsl:template>
</xsl:stylesheet>

当对任何XML文档(未使用)应用此转换时,会产生所需的正确结果(标题是根据全局/外部参数$pLang生成的):

<html>
   <title>Titel in het nederlands</title>
</html>

请注意

建议将所有字符串保存在与XSLT样式表文件分开的XML文档中。这允许在不更改XSLT代码的情况下修改/添加/删除字符串。

要从另一个XML文档访问字符串,代码几乎保持不变,唯一的区别是document()函数的参数现在是字符串XML文档的URI。

答案 1 :(得分:1)

如果您在自己的应用程序中执行转换,则可以使用另一种方法。一种需要一些编码,但可以减少样式表的混乱情况。

样式表:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stylesheet SYSTEM "i18n/humanreadable.ent">
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"...>
    &text1; &text2;

(您可以为i18n目录选择任何您喜欢的名称,请记住它起着特殊的作用。)

可读性:

<!ENTITY text1 "Hello">
<!ENTITY text2 "world!">

到目前为止,这仍然是一个不错的老旧有效XSLT。但是,尽管它使样式表更具可读性,但并不能为您提供非常理想的多语言支持。为此,您需要进行一些编码。

自定义用来解析样式表文件的文档构建器; 为其分配实体解析器

Source getStylesheetSource(String stylesheetFilename, EntityResolver entityResolver) throws ... {
    DocumentBuilder docBuilder = getDomFactory().newDocumentBuilder();
    docBuilder.setEntityResolver(entityResolver);
    Document stylesheet = docBuilder.parse(new FileInputStream(new File(stylesheetFilename)));
    return new DOMSource(stylesheet);
}

将样式表解析为文档时,每次遇到相对URL /路径时都会调用此实体解析器。
发生这种情况时,请检查路径是否以魔术前缀(您的特殊目录)开头,然后将此前缀转换为指向所需语言的人类可读路径。

final String targetLanguage = figureOutDesiredLanguage(...);
EntityResolver entityResolver = new EntityResolver() {
        @Override
        public InputSource resolveEntity(String publicId, String systemId) throws IOException {
            if (pointsToMySpecialFolder(systemId)) {
                String lang = targetLanguage;
                String i18n = insertLangIntoThePath(systemId, lang);
                return new InputSource(new FileInputStream(new File(i18n)));
            }
            return null;
        }
};

Source stylesheet = getStylesheetSource("stylesheet.xslt", entityResolver);
Result result = new SAXResult(...);
Transformer transformer = transformerFactory.newTransformer(stylesheet);
transformer.transform(new DOMSource(inputXml), result);

缺点很明显:您需要在XML / XSLT之外进行一些编码,并且XSLT样式表仅在超级特殊应用程序中使用时才是多语言的。

好处是在我的XSLT样式表中已经没有多余的标签了。