使用DOM在Java中使用XSLT转换XML [英] Transform XML with XSLT in Java using DOM

查看:170
本文介绍了使用DOM在Java中使用XSLT转换XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在四处寻找Java样本来使用XSLT转换XML文档。我发现了几个使用新文件(path / to / file.xml)的示例来加载XML和XSLT,这些都非常有用。我的问题是我试图在一个新的方法中使用它,它将接受两个 org.w3c.dom.Document 对象。一旦我用 DOMSource 替换用于加载XSLT的 StreamSource ,我的调用结果就是XSLT而不是转换后的XML。

I've been looking around everywhere for Java samples to transform an XML document with an XSLT. I've found several samples using new File("path/to/file.xml") to load in the XML and the XSLT and those work great. My problem is that I'm trying to use this in a new method that will accept two org.w3c.dom.Document objects. As soon as I replace the StreamSource used to load in the XSLT with a DOMSource the result of my call is then the XSLT instead of the transformed XML.

工作代码来自如何从java代码调用XSL模板?

Source xmlInput = new StreamSource(new File("c:/path/to/input.xml"));
Source xsl = new StreamSource(new File("c:/path/to/file.xsl"));
Result xmlOutput = new StreamResult(new File("c:/path/to/output.xml"));

try {
    Transformer transformer =     TransformerFactory.newInstance().newTransformer(xsl);
    transformer.transform(xmlInput, xmlOutput);
} catch (TransformerException e) {
    // Handle.
}

我的代码:

public static Document transformXML(Document xml, Document xslt) throws TransformerException, UnsupportedEncodingException, SAXException, IOException, ParserConfigurationException, FactoryConfigurationError{

    Source xmlSource = new DOMSource(xml);
    Source xsltSource = new DOMSource(xslt);
    StreamResult result = new StreamResult(new StringWriter());

    // the factory pattern supports different XSLT processors
    TransformerFactory transFact =
            TransformerFactory.newInstance();
    Transformer trans = transFact.newTransformer(xsltSource);

    trans.transform(xmlSource, result);

    Document resultDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(result.getWriter().toString().getBytes("utf-8")));

    return resultDoc;
}

我的结果文档是XSLT而不是XML。我用 DOMSource 做错了什么?

My result document is then the XSLT instead of the XML. What am I doing wrong with the DOMSource?

推荐答案

XSLT和XPath只有使用名称空间感知的DOM实现和DOM树才有意义,这就是为什么我问你使用名称空间感知文档构建器构建变换器的DOM树吗?在我的评论中。

XSLT and XPath only make sense with a namespace aware DOM implementation and DOM tree, that is why I asked "Are the DOM trees you feed to the transformer built with a namespace aware document builder?" in my comment.

据我使用Oracle Java 1.8进行测试时,当一个不支持命名空间的 DocumentBuilderFactory 并使用内置的 Transformer ,您的方法返回样式表代码。但是,只要我将 DocumentBuilderFactory 更改为名称空间感知,结果就是预期的。

As far as I have tested with Oracle Java 1.8, when a not namespace-aware DocumentBuilderFactory and the built-in Transformer is used, your method returns the stylesheet code. However as soon as I change the DocumentBuilderFactory to be namespace aware, the result is as intended.

这是工作样本:

package domsourcetest1;

import java.io.IOException;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.xml.sax.SAXException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;

/**
 *
 * @author Martin Honnen
 */
public class DOMSourceTest1 {


    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, TransformerException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document xslt = db.parse("sheet1.xsl");
        Document xml = db.newDocument();
        xml.appendChild(xml.createElementNS(null, "root"));
        Document result = transformXML(xml, xslt);
        System.out.println(result.getDocumentElement().getTextContent());
        LSSerializer serializer = ((DOMImplementationLS) xml.getImplementation()).createLSSerializer();
        System.out.println(serializer.writeToString(result));
    }

    public static Document transformXML(Document xml, Document xslt) throws TransformerException, ParserConfigurationException, FactoryConfigurationError {

        Source xmlSource = new DOMSource(xml);
        Source xsltSource = new DOMSource(xslt);
        DOMResult result = new DOMResult();

        // the factory pattern supports different XSLT processors
        TransformerFactory transFact
                = TransformerFactory.newInstance();
        Transformer trans = transFact.newTransformer(xsltSource);

        trans.transform(xmlSource, result);

        Document resultDoc = (Document) result.getNode();

        return resultDoc;
    }
}

示例样式表只输出有关XSLT处理器的信息:

The sample stylesheet simply outputs information about the XSLT processor:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <debug>
            <xsl:value-of select="system-property('xsl:vendor')"/>
        </debug>
    </xsl:template>

</xsl:stylesheet>

该计划的输出是

Apache Software Foundation (Xalan XSLTC)
<?xml version="1.0" encoding="UTF-16"?>
<debug>Apache Software Foundation (Xalan XSLTC)</debug>

现在当我注释掉 // dbf.setNamespaceAware(true); main 方法中,结果是

Now when I comment out //dbf.setNamespaceAware(true); in the main method the result is

<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/"><debug><xsl:value-of select="system-property('xsl:vendor')"/></debug></xsl:template></xsl:stylesheet>

意味着结果确实是样式表文档。这显然是一个错误,或者至少是内置Xalan Transformer的怪癖,当我把Saxon 6.5.5放在类路径上时,问题不会发生,类路径上的Saxon 9.6也不会发生。

meaning the result is indeed the stylesheet document. That is obviously a bug or at least a quirk with the built-in Xalan Transformer, when I put Saxon 6.5.5 on the class path the problem does not occur, nor does it occur with Saxon 9.6 on the class path.

但是,一般情况下,当使用XSLT或XPath而不是名称空间感知的DOM树时,我认为你不会得到有意义的结果。还看到的Xalan释放DOM2DOM样品 http://svn.apache.org/viewvc/xalan/java/tags/xalan-j_2_7_2/samples/DOM2DOM/DOM2DOM.java?revision=1695338&view=markup 其说

In general, however, I don't think you will get meaningful results when using XSLT or XPath with not namespace aware DOM trees. See also the DOM2DOM sample in the Xalan release http://svn.apache.org/viewvc/xalan/java/tags/xalan-j_2_7_2/samples/DOM2DOM/DOM2DOM.java?revision=1695338&view=markup which says

  // And setNamespaceAware, which is required when parsing xsl files
  dFactory.setNamespaceAware(true);

这篇关于使用DOM在Java中使用XSLT转换XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆