当我取消注释以下代码中的一行时,我得到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)
让我们用一个共同的来源进行测试。
的test.xml
<?xml version="1.0" encoding="UTF-8"?>
<tests>
<test>
<text>Hi!</text>
</test>
</tests>
test.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>
在适当的地方(在答案中)查看我的答案。
答案 0 :(得分:4)
DOMResult output = new DOMResult();
TransformerFactory.newInstance().
newTransformer(new StreamSource(xsl)).
transform(input, output);
return (Document) output.getNode();
的参考:强>
DOMResult#getNode()
获取将包含结果DOM树的节点。如果没有通过DOMResult(节点节点)设置节点,...,那么节点将由转换设置,并且可以在转换完成后从该方法获得。
答案 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)
与你的不完全相同(见后面的内容!)但是替换输出System.out,我得
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 :(得分:1)
XSL 文件中的XHTML是正确的(XML兼容),但XSLT处理后的输出不是。
我看了一行(在XSLT proc的输出中):
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
meta
全部为大写,>
应为/>
。
所以我改变了从method
html
的行
<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处理器对其进行了测试,并且可以正常工作。