前面两篇:Struts2 使用 XSLTResult 输出页面内容详解 和 Struts2 使用 xslt 结果类型如何把字符串直接作为 Document 内容 对 Struts2 如何使用 xslt 结果和怎么把字符串直接作为 Document 内容进行的讲解、研究和探讨。关于 Action 中的字符怎么直接作为 xslt 的内容已有一种方法,就是把 String 转换成 org.w3c.dom.Document 类型再送给 xslt 文件。
同时也发现 Struts2 使用了 org.apache.struts2.views.xslt.StringAdapter 了对字符串的处理,并提供了 parseStringAsXML 的开关选项(虽然是无从设置它的值),但即使把 parseStringAsXML 设置成了 true,送给 xslt 文件的内容也是被包裹上了 <result> 根节点,xslt 中不得不用 <xsl:template match="/result/你的根节点"> 来应用模板。
通过在上一篇 Struts2 使用 xslt 结果类型如何把字符串直接作为 Document 内容 里琢磨来琢磨去的探寻,着实又走了不少弯路,甚至是误入了歧途,但终究是找到了一个较好的办法来让 Action 直接送 String 表示的 Document 给 xslt 文件。那就是自定义 StringXSLTResult,继承自 org.apache.struts2.views.xslt.XSLTResult,只需要覆盖它的 getDOMSourceForStack(Object value) 方法。完整的 StringXSLTResult 类代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package cc.unmi.teststruts2.webcontext; import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; import org.apache.struts2.views.xslt.XSLTResult; import org.xml.sax.InputSource; /** * 自定义的 XSLTResult,默认会把字符串直接转换为 Document,保持原来的结构 * <br/> 这和 StringAdapter 的 ParseStringAsXML 是不同的,不会包上 <result> 节点 * parseStringAsXML 默认为 true * @see org.apache.struts2.views.xslt.StringAdapter * @author Unmi * CreateTime: Apr 12, 2011 */ @SuppressWarnings("serial") public class StringXSLTResult extends XSLTResult { private boolean parseStringAsXML = true; public void setParseStringAsXML(boolean parseStringAsXML) { this.parseStringAsXML = parseStringAsXML; } @Override protected Source getDOMSourceForStack(Object value) throws IllegalAccessException, InstantiationException { //是字符串且 parseStringAsXML 为 true 时,直接转换为 org.w3c.dom.Document //出现异常或其他条件时沿用传统的 XSLTResult 处理方式 if(parseStringAsXML && value instanceof String){ try { DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); value = builder.parse(new InputSource(new StringReader((String)value))); } catch (Exception e) { //throw new IllegalAccessException("Can't cast value to Document type."); return super.getDOMSourceForStack(value); } } return super.getDOMSourceForStack(value); } } |
现在如何使用它呢,先要在 struts.xml 文件中配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="unmi" namespace="/" extends="struts-default"> <result-types> <!-- 定义 StringXSLTResult, 为区别与内置的 xslt, 我们命名为 sxslt --> <result-type name="sxslt" class="cc.unmi.teststruts2.webcontext.StringXSLTResult"/> </result-types> <action name="user" class="cc.unmi.teststruts2.action.UserAction"> <result type="sxslt"> <!-- 这里使用上面定义的 sxslt, 其他属性与 xslt 是一样的 --> <param name="exposedValue">xmlString</param> <param name="stylesheetLocation ">/xslt/user.xslt</param> <param name="noCache">true</param> </result> </action> </package> </struts> |
现在 Action 中只需要向 xslt 直接输送字符串就行:
1 2 3 4 5 6 |
public String execute(){ String xmlString = "<user><name>Unmi</name></user>" Map<String, Object> contextMap = ActionContext.getContext().getContextMap(); contextMap.put("xmlString", xmlString); return SUCCESS; } |
在 /xslt/user.xslt 里,<user> 就是它所要处理 Document 的根节点了,没有额外的 <result>,所以 user.xslt 的内容写成:
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" omit-xml-declaration="yes" /> <xsl:template match="/user"> <xsl:value-of select="name"/> </xsl:template> </xsl:stylesheet> |
上面显示出来的就是 Unmi 了。总之,记住了根节点不再是 <result> 了。以后碰到直接调用 Service 获得的是 XML String 的时候就可以使用这个自定义的 sxslt 结果了。
参考:1. Struts2 使用 XSLTResult 输出页面内容详解
3. Struts2 使用 xslt 结果类型如何把字符串直接作为 Document 内容
本文链接 https://yanbin.blog/struts2-xslt-string-document-final/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。