一、解析XML文件时,遇到DTD的定义要怎么办?
下面这段代码是ibatis配置文件,用w3c Dom(其实任意一种解析方式都是这样)都会从http://www.ibatis.com/dtd/sql-map-config-2.dtd 这 个地址找对应的DTD文件进行校验,如果因特网上这个地址不存在的话,就会报 java.net.ConnectException: Connection timed out: connect 。
- <? xml version = "1.0" encoding = "UTF-8" ?>
- <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
- < sqlMapConfig >
- < settings useStatementNamespaces = "true" />
- <!--防止空SqlMap报错 by zhangbo start -->
- < sqlMap resource = "ibatis/project/project-blank.xml" />
- < sqlMap resource = "ibatis/project/user-mapping.xml" />
- </ sqlMapConfig >
遇到这种问题可以有两种解析方式,第一把DTD下载的本地,指定从本地加载DTD文件;另一种,干脆忽略DTD文件。
这两种方式都是以重新构建实体的解析器(EntityResolver)为基础解决方案的,重新构建实体解析器而不是使用默认的实体解析器,因为默 认的解析器会根据实际的url进行读取,下面是一段如何来解析上面提到的配置文件,两种方式都有标注
- public void addToIbatisTotleConfig() {
- try {
- DocumentBuilderFactory factory = DocumentBuilderFactory
- .newInstance();
- factory.setIgnoringElementContentWhitespace(true );
- DocumentBuilder db = factory.newDocumentBuilder();
- db.setEntityResolver(new EntityResolver(){
- public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
- if (publicId.equals( "-//iBATIS.com//DTD SQL Map Config 2.0//EN" )){
- //这是第一种方式,即忽略DTD,新建一个默认的空XML来代替
- return new InputSource( new ByteArrayInputStream( "<?xml version='1.0' encoding='GBK'?>" .getBytes()));
- //这是第二种方式,即指定本地的DTD文件,当然,这种方式需要把XML文件下载到本地,放入对应的目录中
- // InputStream dtd_stream = this.getClass().getResourceAsStream("..//dtd/sql-map-config-2.dtd");
- // return new InputSource(dtd_stream);
- }
- return null ;
- }});
- String ibatisTotalConfigFileName = ctx.getIbatisTotalConfigFile();
- File ibatisTotalConfigFile = new File(ibatisTotalConfigFileName);
- Document xmldoc = db.parse("file://localhost//" +ibatisTotalConfigFileName);
- Element root = xmldoc.getDocumentElement();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
public void addToIbatisTotleConfig() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder db = factory.newDocumentBuilder();
db.setEntityResolver(new EntityResolver(){
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
if(publicId.equals("-//iBATIS.com//DTD SQL Map Config 2.0//EN")){
//这是第一种方式,即忽略DTD,新建一个默认的空XML来代替
return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='GBK'?>".getBytes()));
//这是第二种方式,即指定本地的DTD文件,当然,这种方式需要把XML文件下载到本地,放入对应的目录中
// InputStream dtd_stream = this.getClass().getResourceAsStream("..//dtd/sql-map-config-2.dtd");
// return new InputSource(dtd_stream);
}
return null;
}});
String ibatisTotalConfigFileName = ctx.getIbatisTotalConfigFile();
File ibatisTotalConfigFile = new File(ibatisTotalConfigFileName);
Document xmldoc = db.parse("file://localhost//"+ibatisTotalConfigFileName);
Element root = xmldoc.getDocumentElement();
} catch (Exception e) {
e.printStackTrace();
}
}
二、使用W3CDom编辑完上面的XML文件,把document转换为XML文件的时候,DTD定义会丢失,如果要加上,要怎么办?
加DTD定义时,要在转换器中操作,重点使用这个两句代码:
- transformer.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_PUBLIC, doc.getDoctype().getPublicId());
- transformer.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
transformer.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_PUBLIC, doc.getDoctype().getPublicId());
transformer.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
DTD定义的值在document对象中是有的,你可以直接输出,也可以改变。
下面是我的实际应用
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import javax.xml.transform.Transformer;
- import javax.xml.transform.TransformerConfigurationException;
- import javax.xml.transform.TransformerException;
- import javax.xml.transform.TransformerFactory;
- import javax.xml.transform.dom.DOMSource;
- import javax.xml.transform.stream.StreamResult;
- import javax.xml.xpath.XPath;
- import javax.xml.xpath.XPathConstants;
- import javax.xml.xpath.XPathExpressionException;
- import javax.xml.xpath.XPathFactory;
- import org.w3c.dom.Document;
- import org.w3c.dom.Node;
- public static void saveXml(String fileName, Document doc) { // 将Document输出到文件
- TransformerFactory transFactory = TransformerFactory.newInstance();
- try {
- Transformer transformer = transFactory.newTransformer();
- transformer.setOutputProperty("indent" , "yes" );
- DOMSource source = new DOMSource();
- source.setNode(doc);
- System.out.println(doc.getDoctype().getPublicId());
- transformer.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_PUBLIC, doc.getDoctype().getPublicId());
- transformer.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
- StreamResult result = new StreamResult();
- result.setOutputStream(new FileOutputStream(fileName));
- transformer.transform(source, result);
- } catch (TransformerConfigurationException e) {
- e.printStackTrace();
- } catch (TransformerException e) {
- e.printStackTrace();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- }
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public static void saveXml(String fileName, Document doc) {// 将Document输出到文件
TransformerFactory transFactory = TransformerFactory.newInstance();
try {
Transformer transformer = transFactory.newTransformer();
transformer.setOutputProperty("indent", "yes");
DOMSource source = new DOMSource();
source.setNode(doc);
System.out.println(doc.getDoctype().getPublicId());
transformer.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_PUBLIC, doc.getDoctype().getPublicId());
transformer.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
StreamResult result = new StreamResult();
result.setOutputStream(new FileOutputStream(fileName));
transformer.transform(source, result);
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}