解析XML时DTD的处理--解析时忽略,生成XML文件时加上。-- XML进阶
一、解析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();}}?
?
二、使用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());?
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(); } }?
三、用w3c dom 解析帶有DTD定義的XML時,會給一些元素自動加些一默認屬性,例如:下面Spring的代碼:
?
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans default-autowire="no" default-dependency-check="none"default-lazy-init="false"><bean autowire="default"class="org.springframework.context.support.ClassPathXmlApplicationContext"dependency-check="default" id="galaxyBaseContext" lazy-init="true"><constructor-arg><list><value>spring/base-context.xml</value></list></constructor-arg></bean><bean autowire="default"class="org.springframework.context.support.ClassPathXmlApplicationContext"dependency-check="default" id="galaxyContext" lazy-init="true"><constructor-arg><list>?
default-autowire="no" default-dependency-check="none" default-lazy-init="false" 這三個屬性是自動加的,其實我只是用W3c Dom解析后改變了一個bean元素的屬性值,但是解析完,bean都會加前面三個屬性,很麻煩,也可以用第一種方法解決,設置DTD忽略,忽略以后并不會影響第二點講的解析完增加DTD。
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的解析XML时DTD的处理--解析时忽略,生成XML文件时加上。-- XML进阶的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用setTimeout方法控制JS中方
- 下一篇: 树-当前结点与列表页不符的处理