Java 使用DOMResult进行XML转换

Java 使用DOMResult进行XML转换,java,xml,xslt,Java,Xml,Xslt,当我在以下代码中取消注释一行时,我得到了java.lang.NullPointerException: private static Document XSLT(String name) throws Exception{ File xsl = new File("data/" + name + ".xsl"); File xml = new File("data/" + name + ".xml"); DocumentBuilder db = DocumentBuild

当我在以下代码中取消注释一行时,我得到了
java.lang.NullPointerException

private static Document XSLT(String name) throws Exception{
    File xsl = new File("data/" + name + ".xsl");
    File xml = new File("data/" + name + ".xml");
    DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document document = db.newDocument();
    DOMSource input = new DOMSource(db.parse(xml));
    StreamResult output = new StreamResult(System.out); //That works but its not what I want!
    //DOMResult output = new DOMResult(document); //that gives the null pointer exception
    TransformerFactory.newInstance().newTransformer(new StreamSource(xsl)).transform(input, output);
    return document;
}
我的意图是使用XSLT和Java语言创建这样的方法来帮助我转换XML文件。毕竟,在保存到文件之前,我应该做所有的转换

如何从该方法中获取文档

我的意思是,我不想将转换后的文档保存到一个文件中以便加载它,我只想在“内存”中这样做

谢谢:)

更新 让我发布例外情况,以便您能更好地帮助我

Exception in thread "main" javax.xml.transform.TransformerException: java.lang.NullPointerException
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:736)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:340)
        at test.Main.XSLT(Main.java:393)
        at test.Main.test(Main.java:342)
        at test.Main.main(Main.java:329)
Caused by: java.lang.NullPointerException
        at com.sun.org.apache.xml.internal.serializer.SerializerBase.patchName(SerializerBase.java:271)
        at com.sun.org.apache.xml.internal.serializer.SerializerBase.addAttribute(SerializerBase.java:429)
        at com.sun.org.apache.xml.internal.serializer.ToSAXHandler.addUniqueAttribute(ToSAXHandler.java:438)
        at xmlname.template$dot$0()
        at xmlname.applyTemplates()
        at xmlname.transform()
        at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(AbstractTranslet.java:611)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:729)
        ... 4 more
---------
java.lang.NullPointerException
        at com.sun.org.apache.xml.internal.serializer.SerializerBase.patchName(SerializerBase.java:271)
        at com.sun.org.apache.xml.internal.serializer.SerializerBase.addAttribute(SerializerBase.java:429)
        at com.sun.org.apache.xml.internal.serializer.ToSAXHandler.addUniqueAttribute(ToSAXHandler.java:438)
        at xmlname.template$dot$0()
        at xmlname.applyTemplates()
        at xmlname.transform()
        at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(AbstractTranslet.java:611)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:729)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:340)
        at test.Main.XSLT(Main.java:393)
        at test.Main.test(Main.java:342)
        at test.Main.main(Main.java:329)
更新2 让我们使用公共源进行测试

test.xml

解决了的 在适当的位置查看我的答案(在答案中!)

参考:

获取将包含结果DOM树的节点。如果没有通过DOMResult(节点节点)设置节点,然后通过转换设置节点,一旦转换完成,就可以通过该方法获得节点


我怀疑转换的输出不是格式良好的
XML
。我可以通过以下代码和输入文件获得相同的异常

XmlTransform.java

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import java.io.*;
import org.w3c.dom.*;

public class XmlTransform {
    public static void main(String[] args) throws Exception {
        File xsl = new File("1.xsl");
        File xml = new File("1.xml");
        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document document = db.newDocument();
        DOMSource input = new DOMSource(db.parse(xml));

//        StreamResult output = new StreamResult(System.out); //That works but its not what I want!
        DOMResult output = new DOMResult(document); //that gives the null pointer exception
        TransformerFactory.newInstance().newTransformer(new StreamSource(xsl)).transform(input, output);

        System.out.println("getNode().getLocalName()=" + output.getNode().getLocalName());
        System.out.println("((Document)getNode()).getDocumentElement().getLocalName()=" + ((Document)output.getNode()).getDocumentElement().getLocalName());

        Node n = ((Document)output.getNode()).getDocumentElement();

        System.out.println("n.hasChildNodes()=" + n.hasChildNodes());
        System.out.println("Beatles=" + n.getChildNodes().getLength());
    }
}
1.xml

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
    <xsl:apply-templates select="//beatle" />
</xsl:template>

<xsl:template match="beatle">
  <xsl:value-of select="name/first"/>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<beatles>
  <beatle>
    <name>
      <first>John</first>
      <last>Lennon</last>
    </name>
  </beatle>
  <beatle>
    <name>
      <first>Paul</first>
      <last>McCartney</last>
    </name>
  </beatle>
  <beatle>
    <name>
      <first>George</first>
      <last>Harrison</last>
    </name>
  </beatle>
  <beatle>
    <name>
      <first>Ringo</first>
      <last>Starr</last>
    </name>
  </beatle>
</beatles>
这与您的不完全相同(见下文!),但更换了输出系统。我明白了

JohnPaulGeorgeRingo
正如所料

现在,输出不完全是
XML
,因此,如果您开始向
XSLT
添加元素,例如,让我们用
将每个名称包装为:

<name><xsl:value-of select="name/first"/></name>
因为输出不是格式良好的
XML
文档。XML文档中必须只有一个根节点。因此,通过替换:

    <xsl:apply-templates select="//beatle" />
希望这有帮助。

XSL文件中的XHTML是正确的(符合XML),但XSLT处理后的输出不是正确的

我查看了这行代码(在XSLT过程的输出中):

xml

<xsl:output 
    method="html"
    version="1.0" 
    encoding="utf-8" 
    indent="yes" 
    omit-xml-declaration="no"
    media-type="application/xml"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" 
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
/>
<xsl:output 
    method="xml"
    version="1.0" 
    encoding="utf-8" 
    indent="yes" 
    omit-xml-declaration="no"
    media-type="application/xml"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" 
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
/>
所以一个空div:

    <div/>

将写为:

    <div></div>


我使用默认JDK附带的XSLT处理器对其进行了测试,它可以正常工作。

感谢您的帮助,但无论是否使用
DOMResult
构造函数中的参数,问题都会不断出现。也就是说,您说过使用
newdomresult()
我使用了
newdomresult(document)
但是结果是一样的。我已经知道
getNode()
方法。问题是这个例外。请共享您的输入xml和xslt文件以进一步调试问题。呵呵,谢谢。我再核对一下。但到目前为止,我的XHTML(输出)是XML兼容的,所以我不知道问题出在哪里…:)正如我所看到的,编程是一项艰苦的工作,它肯定不适合懒惰的人!可能是看到有人这样做的第一印象,但事实并非如此!呵呵,你让我仔细检查,我发现了问题!非常感谢。
ERROR: 'HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted. '
    Exception in thread "main" javax.xml.transform.TransformerException: org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:736)
    <xsl:apply-templates select="//beatle" />
    <names><xsl:apply-templates select="//beatle" /></names>
getNode().getLocalName()=null
((Document)getNode()).getDocumentElement().getLocalName()=names
n.hasChildNodes()=true
Beatles=4
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<xsl:output 
    method="html"
    version="1.0" 
    encoding="utf-8" 
    indent="yes" 
    omit-xml-declaration="no"
    media-type="application/xml"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" 
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
/>
<xsl:output 
    method="xml"
    version="1.0" 
    encoding="utf-8" 
    indent="yes" 
    omit-xml-declaration="no"
    media-type="application/xml"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" 
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
/>
    media-type="application/xhtml+xml"
    <div/>
    <div></div>