我做了一个简单的例子来重现这个问题。这是转换(mini.xsl):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<foo>
<xsl:copy-of select="."/>
</foo>
</xsl:template>
</xsl:stylesheet>
这是输入(mini.xml):
<?xml version="1.0" encoding="utf-8"?>
<bar xmlns:x="baz">
<x:baz/>
</bar>
当我用
应用转换时xsltproc mini.xsl mini.xml
结果看起来像预期的那样:
<?xml version="1.0"?>
<foo>
<bar xmlns:x="baz">
<x:baz/>
</bar>
</foo>
但是,当我使用以下Java程序运行转换时,
import java.io.FileInputStream;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class Program
{
public static void main(String[] args)
{
try
{
Source transform = new StreamSource(new FileInputStream(args[0]));
Templates templates = TransformerFactory.newInstance().newTemplates(transform);
Document input = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(args[1]));
Result result = new StreamResult(System.out);
templates.newTransformer().transform(new DOMSource(input), result);
}
catch (TransformerFactoryConfigurationError | ParserConfigurationException | SAXException | IOException | TransformerException e)
{
e.printStackTrace();
}
}
}
结果如下:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar xmlns:x="baz">
<baz/>
</bar>
</foo>
(注意缺少baz前面的x:前缀。)
为什么?
我该怎么办呢(保留命名空间前缀)?
答案 0 :(得分:1)
我只能假设是历史原因,默认情况下DocumentBuilderFactory
非命名空间感知。在执行newDocumentBuilder()
之前,您需要明确地切换命名空间。
最好使用直接占用parse
的{{1}}方法,而不是创建自己的File
(解析完成后代码不会关闭),同样使用构建FileInputStream
的{{1}}。
StreamSource