有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用DOMResult实现java-XML转换

当我在以下代码中取消注释一行时,我得到了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

让我们使用公共源进行测试

测试。xml

<?xml version="1.0" encoding="UTF-8"?>
<tests>
    <test>
        <text>Hi!</text>
    </test>
</tests>

测试。xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <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:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml" lang="pt-BR" xml:lang="pt-BR">           
            <head>
                <meta charset="UTF-8" />
                <title>Test</title>
            </head>
            <body>
                <h1>Test</h1>                       
                <xsl:apply-templates/>
            </body>
        </html> 
    </xsl:template>

    <xsl:template match="/tests/test">
       <p><xsl:value-of select="text"/></p>
    </xsl:template>

</xsl:stylesheet>

使用StreamResult给出以下输出

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="pt-BR" xml:lang="pt-BR" xmlns="http://www.w3.org/1999/xhtml">
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<h1>Test</h1>

<p>Hi!</p>

</body>
</html>

解决

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


共 (3) 个答案

  1. # 1 楼答案

    我怀疑转换的输出不是格式良好的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>
    

    1。xsl

    <?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>
    

    编译并运行此文件时,我会遇到以下异常:

    getNode().getLocalName()=null
        Exception in thread "main" java.lang.NullPointerException
        at XmlTransform.main(XmlTransform.java:27)
    

    这和你的不完全一样(见下文!)但是更换输出系统。出去,我明白了

    JohnPaulGeorgeRingo
    

    正如所料

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

    <name><xsl:value-of select="name/first"/></name>
    

    并切换回DOMResult output这将导致不同的异常:

    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)
    

    因为输出不是格式良好的XML文档。XML文档中必须只有一个根节点。因此,通过替换:

        <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
    

    希望这有帮助

  2. # 2 楼答案

    DOMResult output = new DOMResult();
    TransformerFactory.newInstance().
                       newTransformer(new StreamSource(xsl)).
                       transform(input, output);
    return (Document) output.getNode();
    

    参考资料:
    DOMResult#getNode()

    Get the node that will contain the result DOM tree. If no node was set via DOMResult(Node node), ... , then the node will be set by the transformation, and may be obtained from this method once the transformation is complete.

  3. # 3 楼答案

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

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

    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    

    meta全是大写,而>应该是/>

    因此,我将method的行从html更改为method

    <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"
    />
    

    xml

    <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"
    />
    

    更新

    我遇到了自动关闭标签的问题,然后我不得不改变另一件事,以使输出真正符合浏览器的XHTML

    更改以下行可以修复这些问题:

        media-type="application/xhtml+xml"
    

    所以一个空div:

        <div/>
    

    将写为:

        <div></div>
    

    我使用默认JDK附带的XSLT处理器对其进行了测试,结果证明它是有效的