Java中使用XML字符串和XSLT字符串作为参数获取转换后的字符串,支持xsl:include、xsl:import

2011年末就不做外包了,期间虽然更新过博客园,次数依然少的可怜。

农历新年前分享点实用代码到博客吧。

这次分享的是Java中使用XML字符串和XSLT字符串作为参数获取转换后的结果字符串。

分享的方法仅解决上述问题,对于XSLT字符串中可能存在的XSLT注入问题、大字符串的性能问题未做考虑

关键代码如下:

package Test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.URLDecoder;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.xml.sax.InputSource;

public class Test {
    private static final Logger logger = LogManager.getLogger(Test.class);
    private static final TransformerFactory tFactory = getTransformerFactory();

    public static void main(String[] args) {
        try {
            String xmlStr="<Parameters>\r\n" + 
                    "    <columnId>C5CAB5D6-E8E8-4E90-8FE2-2CCDCB4FE562</columnId>\r\n" + 
                    "    <_>1579165992522</_>\r\n" + 
                    "</Parameters>";
            String xsltStr="<xsl:if test=\"//Parameters/columnId!=''\">" + 
                    "columnId=<xsl:value-of select=\"//Parameters/columnId\"/>" + 
                    "</xsl:if>";
            String resultStr=invokeXmlstrAndXslstr(xmlStr, xsltStr);
            
            System.out.println("xmlStr:");
            System.out.println(xmlStr);
            
            System.out.println("xsltStr:");
            System.out.println(xsltStr);
            
            System.out.println("resultStr:");
            System.out.println(resultStr);
            
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static String invokeXmlstrAndXslstr(String xmlString, String xslString) throws Exception {
        String returnXMLString = "";
        Transformer transformer;
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        PrintWriter printWriter;
        StreamSource source;
        StreamResult result;

        // 补全为XSLT字符串 根据实际应用决定是否需要这部分补全字符串的代码
        xslString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                + "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
                + "<xsl:output method=\"text\" version=\"5.0\" encoding=\"UTF-8\" indent=\"yes\" />"
                + "    <xsl:template match=\"/\">" + xslString + "    </xsl:template>" + "</xsl:stylesheet>";

        transformer = tFactory.newTransformer(new SAXSource(new InputSource(new StringReader(xslString))));

        source = new StreamSource(new StringReader(xmlString));
        bytes = new ByteArrayOutputStream();
        printWriter = new PrintWriter(bytes);
        result = new StreamResult(printWriter);// 存放中间结果

        // 使用指定的样式表,转换XML文档
        transformer.transform(source, result);

        if (bytes != null) {
            returnXMLString = bytes.toString();
        }

        return returnXMLString;
    }

    public static TransformerFactory getTransformerFactory() {
        TransformerFactory tFactoryObj = TransformerFactory.newInstance();
        tFactoryObj.setURIResolver(new URIResolver() {
            public Source resolve(String href, String base) throws TransformerException {
                StreamSource ss = null;
                try {
                    ss = getXSL(href);
                } catch (Exception e) {
                    try {
                        throw e;
                    } catch (Exception e1) {
                        logger.error("获取include的XSLT文件异常!异常信息:", e1);
                    }
                }
                return ss;
            }
        });
        return tFactoryObj;
    }

    /**
     * 指定XSLT内部include或import的XSLT文件的完整路劲 该方法需要根据项目情况调整指定路劲的规则
     * 
     * @param href include或import标签中href属性的值
     * @return include或import的XSLT文件的完整路劲
     * @throws Exception
     */
    public static StreamSource getXSL(String href) throws Exception {
        StreamSource ss;
        String pathVal = Test.class.getResource("/").toString().replace("file:/", "/").replace("/WEB-INF/classes/", "/")
                + href;
        pathVal = pathVal.replaceAll("//", "/");
        pathVal = URLDecoder.decode(pathVal, "utf-8");
        File f = new File(pathVal);
        if (f.exists()) {
            ss = new StreamSource(new FileInputStream(f));
        } else {
            f = new File("src/main/resources/xslt/" + href);
            if (f.exists()) {
                ss = new StreamSource(new FileInputStream(f));
            } else {
                ss = new StreamSource(Test.class.getResource("/xslt/" + href).openStream());
            }
        }
        return ss;
    }

}

本文首发于我的CSDN博客:https://blog.csdn.net/n_ithero/article/details/104006183

posted @ 2020-01-22 14:00  志在必得Shaun  阅读(528)  评论(0编辑  收藏  举报