开发XSLT解决方案可以很简单,只需要少量的工作执行转换。但是,有时候源文档和目标文档是比较复杂的,不同的。很多这种情况下,复杂的转换是通过等价的XSLT复杂转换实现的。
有些转换使用普通的XSLT功能是没法做到的。这种情况下,你可以使用Apache Xalan XSLT引擎和自定义的Java扩展在你的样式表里加入新函数。
一个例子
让我们从测试一个简单的例子开始吧。假设你正在转换一个XML文档,你需要在转换过程中执行很多高级的操作。你也许需要参考历遍一个数据库中的表或者访问一个Web服务。这些函数很简单,但是XSLT没有直接提供。
我们假设:有了一个简单的定购XML文档,如清单1所示。那么问题是:我们的转换过程需要翻转Description元素中的字符。也许,它不符合现实世界中的情况,但是它可以演示了。
清单1:order.xml
〈Order〉
〈Items〉
〈Item〉
〈SKU〉45353〈/SKU〉
〈Description〉Mechawidget Flange〈/Description〉
〈/Item〉
〈Item〉
〈SKU〉57123〈/SKU〉
〈Description〉Hydrafluant Magnet〈/Description〉
〈/Item〉
〈Item〉
〈SKU〉662354〈/SKU〉
〈Description〉Generic Rubber Seal〈/Description〉
〈/Item〉
〈Item〉
〈SKU〉867623〈/SKU〉
〈Description〉Fluxating Plasmatron〈/Description〉
〈/Item〉
〈/Items〉
〈/Order〉
解决方法
我们的解决方法是使用Apache Xalan XSL 处理器,并从它扩展出一个Java类。这个Java组件实现字符串数据的转换工作。XSL样式表访问这个Java类,把XML数据传进去,在XML结果文档中显示返回值。每一步都列在下面了。
Java部分
为了解决这个问题,我们首先需要写一个完成这个工作的Java代码。既然这样,我们将使用一个简单的字符串翻转类,如清单2所示:
清单2:
Reverse.java
public class Reverse {
public static String reverse(String str) {
String retval = "";
char[] ch = new char[str.length()];
str.getChars(0, str.length(), b, 0);
for (int i = (ch.length - 1); i 〉= 0; i--) {
retval += ch[i];
}
return retval;
}
}
这个类只有一个静态方法:reverse。这个方法的有一个String参数,返回一个字符串。这个函数将翻转字符串:从String类从读取字符到一个字符数组,然后从数组的尾部历遍字符。
XSLT部分
为了在XSL样式表中使用Java类,你需要声明一个XML命名空间。这个命名空间会识别调用Java类的格式。这里有3个不同的命名空间的格式供你使用:我们演示其中一个,Java格式如下:
xmlns:java=http://xml.apache.org/xalan/java
除了要声明java命名空间外,我们还需要设置〈xsl:stylesheet〉 元素的exclude-result-prefixes属性。这个属性会避免Java命名空间出现在输出文档里。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" xmlns:java="http://xml.apache.org/xalan/java"
exclude-result-prefixes="java">
<xsl:variable name="lab_run_class_info" select="java:com.cw.wiw.util.LangLabel.getValue($wb_lang_encoding, '1173')" />
为了在XSL样式表里正确地调用Java组件,你需要指定类,方法和传入的参数。类必须以命名空间为前缀。比如,调用我们Reverse类的reverse()方法,就要这样做:
〈xsl:value-of select=“java:Reverse.reverse(′This is a test′)” /〉