`
fqtrnt
  • 浏览: 9810 次
社区版块
存档分类
最新评论

关于在DOM4J在读取XML文件时,解释DTD的问题

阅读更多

近日在使用 DOM4J 的时候,遇到一个问题,现在有两个解决方法,先记下来,以便日后使用。

问题:对一个 XML 文件进行读写操作,但是发现当文件存在的时候,使用DOM4J读进来的时候,生成的 Document 对象会根据 DTD 里的定义,追加了一些 default 属性(实际不需要)。而且在读取的时间被延长。


有一个 XML 文件如下:<o:p></o:p>

xml 代码
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3.   
  4. <beans>   
  5.   ....  
  6. </beans>  

使用 DOM4J 的读取文件的一般性写法:<o:p></o:p>

java 代码
 
  1. SAXReader reader = new SAXReader(false);  
  2. document = reader.read(file);  
  3. root = document.getRootElement();  

对象 document 里的节点会被自动追加 DTD 里的定义的 default 属性,只有新增加的节点不受影响,如下。而且,如果文件的操作时间被延长。

xml 代码
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3.   
  4. <beans default-lazy-init="false" default-autowire="no" default-dependency-check="none">   
  5.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase" lazy-init="default" autowire="default" dependency-check="default"/>    
  6.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase" lazy-init="default" autowire="default" dependency-check="default"/>    
  7.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase" lazy-init="default" autowire="default" dependency-check="default"/>    
  8.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase" lazy-init="default" autowire="default" dependency-check="default"/>    
  9.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase" lazy-init="default" autowire="default" dependency-check="default"/>    
  10.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase" lazy-init="default" autowire="default" dependency-check="default"/>    
  11.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase" lazy-init="default" autowire="default" dependency-check="default"/>    
  12.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase"/>    
  13.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase"/>    
  14.   <bean id="OperateXmlByDom4jTestCase" class="test.OperateXmlByDom4jTestCase"/>  
  15. </beans>  
<o:p></o:p>

为了不让生成我们不需要的 default 属性和缩短文件的操作时间,我们可以调用 SAXReader.setFeature 方法来改变 DOM4J 的行为,片断代码如下:<o:p></o:p>

java 代码
 
  1. // http://apache.org/xml/features/nonvalidating/load-external-dtd"  
  2. saxReader.setFeature(  
  3.     Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE,   
  4.     false);  

关于更多的 Feature 请参考 com.sun.org.apache.xerces.internal.impl.Constants<o:p></o:p>

以下为片断代码:<o:p></o:p>

java 代码
 
  1. // xerces features  
  2.   
  3. /** Xerces features prefix ("http://apache.org/xml/features/"). */  
  4. public static final String XERCES_FEATURE_PREFIX = "http://apache.org/xml/features/";  
  5.   
  6. /** Schema validation feature ("validation/schema"). */  
  7. public static final String SCHEMA_VALIDATION_FEATURE = "validation/schema";  
  8.   
  9. /** Expose schema normalized values */  
  10. public static final String SCHEMA_NORMALIZED_VALUE = "validation/schema/normalized-value";  
  11.   
  12. /** Send schema default value via characters() */  
  13. public static final String SCHEMA_ELEMENT_DEFAULT = "validation/schema/element-default";  
  14.   
  15. /** Schema full constraint checking ("validation/schema-full-checking"). */  
  16. public static final String SCHEMA_FULL_CHECKING = "validation/schema-full-checking";  
  17.   
  18. /** Augment Post-Schema-Validation-Infoset */  
  19. public static final String SCHEMA_AUGMENT_PSVI = "validation/schema/augment-psvi";  
  20.   
  21. /** Dynamic validation feature ("validation/dynamic"). */  
  22. public static final String DYNAMIC_VALIDATION_FEATURE = "validation/dynamic";  
  23.   
  24. /** Warn on duplicate attribute declaration feature ("validation/warn-on-duplicate-attdef"). */  
  25. public static final String WARN_ON_DUPLICATE_ATTDEF_FEATURE = "validation/warn-on-duplicate-attdef";  
  26.   
  27. /** Warn on undeclared element feature ("validation/warn-on-undeclared-elemdef"). */  
  28. public static final String WARN_ON_UNDECLARED_ELEMDEF_FEATURE = "validation/warn-on-undeclared-elemdef";  
  29.   
  30. /** Warn on duplicate entity declaration feature ("warn-on-duplicate-entitydef"). */  
  31. public static final String WARN_ON_DUPLICATE_ENTITYDEF_FEATURE = "warn-on-duplicate-entitydef";  
  32.   
  33. /** Allow Java encoding names feature ("allow-java-encodings"). */  
  34. public static final String ALLOW_JAVA_ENCODINGS_FEATURE = "allow-java-encodings";  
  35.   
  36. /** Disallow DOCTYPE declaration feature ("disallow-doctype-decl"). */  
  37. public static final String DISALLOW_DOCTYPE_DECL_FEATURE = "disallow-doctype-decl";  
  38.   
  39. /** Continue after fatal error feature ("continue-after-fatal-error"). */  
  40. public static final String CONTINUE_AFTER_FATAL_ERROR_FEATURE = "continue-after-fatal-error";  
  41.   
  42. /** Load dtd grammar when nonvalidating feature ("nonvalidating/load-dtd-grammar"). */  
  43. public static final String LOAD_DTD_GRAMMAR_FEATURE = "nonvalidating/load-dtd-grammar";  
  44.   
  45. /** Load external dtd when nonvalidating feature ("nonvalidating/load-external-dtd"). */  
  46. public static final String LOAD_EXTERNAL_DTD_FEATURE = "nonvalidating/load-external-dtd";  
  47.   
  48. /** Defer node expansion feature ("dom/defer-node-expansion"). */  
  49. public static final String DEFER_NODE_EXPANSION_FEATURE = "dom/defer-node-expansion";  
  50.   
  51. /** Create entity reference nodes feature ("dom/create-entity-ref-nodes"). */  
  52. public static final String CREATE_ENTITY_REF_NODES_FEATURE = "dom/create-entity-ref-nodes";  
  53.   
  54. /** Include ignorable whitespace feature ("dom/include-ignorable-whitespace"). */  
  55. public static final String INCLUDE_IGNORABLE_WHITESPACE = "dom/include-ignorable-whitespace";  
  56.   
  57. /** Default attribute values feature ("validation/default-attribute-values"). */  
  58. public static final String DEFAULT_ATTRIBUTE_VALUES_FEATURE = "validation/default-attribute-values";  
  59.   
  60. /** Validate content models feature ("validation/validate-content-models"). */  
  61. public static final String VALIDATE_CONTENT_MODELS_FEATURE = "validation/validate-content-models";  
  62.   
  63. /** Validate datatypes feature ("validation/validate-datatypes"). */  
  64. public static final String VALIDATE_DATATYPES_FEATURE = "validation/validate-datatypes";  
  65.   
  66. /** Notify character references feature (scanner/notify-char-refs"). */  
  67. public static final String NOTIFY_CHAR_REFS_FEATURE = "scanner/notify-char-refs"; 
  68.  
  69. /** Notify built-in (&, etc.) references feature (scanner/notify-builtin-refs"). */  
  70. public static final String NOTIFY_BUILTIN_REFS_FEATURE = "scanner/notify-builtin-refs";  
  71.   
  72. /** Standard URI conformant feature ("standard-uri-conformant"). */  
  73. public static final String STANDARD_URI_CONFORMANT_FEATURE = "standard-uri-conformant";  
  74.   
  75. /** Internal performance related feature:  
  76.  * false - the parser settings (features/properties) have not changed between 2 parses 
  77.  * true - the parser settings have changed between 2 parses   
  78.  * NOTE: this feature should only be set by the parser configuration. 
  79.  */  
  80. public static final String PARSER_SETTINGS = "internal/parser-settings";  
  81.   
  82. /** Feature to make XML Processor XInclude Aware */  
  83. public static final String XINCLUDE_AWARE = "xinclude-aware";  
  84.   
  85. /** Ignore xsi:schemaLocation and xsi:noNamespaceSchemaLocation. */  
  86. public static final String IGNORE_SCHEMA_LOCATION_HINTS = "validation/schema/ignore-schema-location-hints";  
  87.   
  88. /** 
  89.  * When true, the schema processor will change characters events 
  90.  * to ignorableWhitespaces events, when characters are expected to 
  91.  * only contain ignorable whitespaces. 
  92.  */  
  93. public static final String CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES =  
  94.     "validation/change-ignorable-characters-into-ignorable-whitespaces";  

除通过上面的 SAXReader.setFeature 文件之外 ,我们还可以通过自己的 EntityResolver 来解决这个问题。<o:p></o:p>

PS:这个方法是从凝香小筑BLOG的一编主题是:Do not resolve DTD files when dom4j read xml file 的文章里看到的。地址:http://blog.csdn.net/lessoft/archive/<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="20" month="6" year="2007">2007/06/20</st1:chsdate>/1659579.aspx<o:p></o:p>

代码片断如下:<o:p></o:p>

java 代码
 
  1. saxReader.setEntityResolver(new EntityResolver() {  
  2.       
  3.     String emptyDtd = "";  
  4.                       
  5.     ByteArrayInputStream bytels = new ByteArrayInputStream(emptyDtd.getBytes());  
  6.                       
  7.     public InputSource resolveEntity(String publicId, String systemId)   
  8.            throws SAXException, IOException {  
  9.         return new InputSource(bytels);  
  10.     }  
  11. });  



<o:p> </o:p>

完整的代码如下:<o:p></o:p>

java 代码
 
  1. package test;  
  2.   
  3. import java.io.BufferedWriter;  
  4. import java.io.ByteArrayInputStream;  
  5. import java.io.File;  
  6. import java.io.FileWriter;  
  7. import java.io.IOException;  
  8.   
  9. import junit.framework.TestCase;  
  10.   
  11. import org.dom4j.Document;  
  12. import org.dom4j.DocumentHelper;  
  13. import org.dom4j.Element;  
  14. import org.dom4j.io.OutputFormat;  
  15. import org.dom4j.io.SAXReader;  
  16. import org.dom4j.io.XMLWriter;  
  17. import org.dom4j.tree.DefaultDocumentType;  
  18. import org.xml.sax.EntityResolver;  
  19. import org.xml.sax.InputSource;  
  20. import org.xml.sax.SAXException;  
  21.   
  22. import com.sun.org.apache.xerces.internal.impl.Constants;  
  23.   
  24. /** 
  25.  * A test case class for read and writer a xml file by Dom4j. 
  26.  * @author X.F.Yang [2007/07/03] 
  27.  * @version 1.0 
  28.  */  
  29. public class OperateXmlByDom4jTestCase extends TestCase {  
  30.   
  31.     /** 
  32.      * Default way to read and writer a xml file by Dom4j. 
  33.      * @throws Exception 
  34.      */  
  35.     public void testWriteXml() throws Exception {  
  36.         XmlFileOperation operation = new XmlFileOperation();  
  37.         operation.writer(new SAXReaderWrapper() {  
  38.             public void operation(SAXReader saxReader) throws Exception {  
  39.                 // Nothing to do.  
  40.             }  
  41.         });  
  42.     }  
  43.   
  44.     /** 
  45.      * Do not resolve DTD files when dom4j read xml file via the set feature.  
  46.      * @throws Exception 
  47.      */  
  48.     public void testWriteXmlSetFeature() throws Exception {  
  49.         XmlFileOperation operation = new XmlFileOperation();  
  50.         operation.writer(new SAXReaderWrapper() {  
  51.             public void operation(SAXReader saxReader) throws Exception {  
  52.                 // http://apache.org/xml/features/nonvalidating/load-external-dtd"  
  53.                 saxReader.setFeature(  
  54.                         Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE,   
  55.                         false);  
  56.             }  
  57.         });  
  58.     }  
  59.       
  60.     /** 
  61.      * Do not resolve DTD files when dom4j read xml file via implement {@link EntityResolver}.  
  62.      * @throws Exception 
  63.      */  
  64.     public void testWriteXmlEntityResolver() throws Exception {  
  65.         XmlFileOperation operation = new XmlFileOperation();  
  66.         operation.writer(new SAXReaderWrapper() {  
  67.             public void operation(SAXReader saxReader) throws Exception {  
  68.                 saxReader.setEntityResolver(new EntityResolver() {  
  69.                       
  70.                     String emptyDtd = ""; 
  71.                      
  72.                     ByteArrayInputStream bytels = new ByteArrayInputStream(emptyDtd.getBytes()); 
  73.                      
  74.                     public InputSource resolveEntity(String publicId, 
  75.                             String systemId) throws SAXException, IOException { 
  76.                         return new InputSource(bytels); 
  77.                     } 
  78.                 }); 
  79.             } 
  80.         }); 
  81.     } 
  82.      
  83.     /** */ 
  84.     protected interface SAXReaderWrapper { 
  85.          
  86.         /** operation {@link SAXReader} */ 
  87.         void operation(SAXReader saxReader) throws Exception; 
  88.          
  89.     } 
  90.      
  91.     /**  
  92.      * when the target file was existed, read and append the new element. 
  93.      * else, create a new xml file and add the new element. 
  94.      */ 
  95.     protected class XmlFileOperation { 
  96.          
  97.         /** target file */ 
  98.         private File file; 
  99.          
  100.         public XmlFileOperation() { 
  101.             // target file 
  102.             file = new File("d:\\spring.xml"); 
  103.         } 
  104.          
  105.         /** 
  106.          * Write xml file 
  107.          * @param wrapper  
  108.          * @throws Exception 
  109.          * @see {@link SAXReaderWrapper} 
  110.          */ 
  111.         public void writer(SAXReaderWrapper wrapper) throws Exception { 
  112.             try { 
  113.                 Document document = null; 
  114.                 Element root = null; 
  115.                  
  116.                 // read the xml file if target file was existed  
  117.                 if (file.exists()) { 
  118.                     SAXReader reader = new SAXReader(false); 
  119.                      
  120.                     wrapper.operation(reader); 
  121.                      
  122.                     document = reader.read(file); 
  123.                     root = document.getRootElement(); 
  124.                 // if the target file was not existed, create a new one 
  125.                 } else { 
  126.                     document = DocumentHelper.createDocument(); 
  127.                     document.setDocType(new DefaultDocumentType("beans",  
  128.                             "-//SPRING//DTD BEAN//EN",   
  129.                             "http://www.springframework.org/dtd/spring-beans.dtd"));  
  130.                     root = document.addElement("beans"); 
  131.                 } 
  132.                 // create the element under the root element 
  133.                 root.addElement("bean") 
  134.                     .addAttribute("id", "OperateXmlByDom4jTestCase") 
  135.                     .addAttribute("class", "test.OperateXmlByDom4jTestCase");  
  136.                   
  137.                 // writer the document  
  138.                 writer(document);  
  139.             } catch (Exception e) {  
  140.                 e.printStackTrace();  
  141.                 throw e;  
  142.             }  
  143.         }  
  144.           
  145.         protected void writer(Document document) throws Exception {  
  146.             XMLWriter xmlWriter = null;  
  147.             try {  
  148.                 final OutputFormat format = OutputFormat.createPrettyPrint();  
  149.                 xmlWriter = new XMLWriter(new BufferedWriter(new FileWriter(file)), format);  
  150.                 xmlWriter.write(document);  
  151.             } finally {  
  152.                 if (null != xmlWriter) {  
  153.                     xmlWriter.flush();  
  154.                     xmlWriter.close();  
  155.                 }  
  156.             }  
  157.         }  
  158.     }  
  159. }  
分享到:
评论

相关推荐

    DOM4J解析XML时DTD路径问题

    在处理XML文件时,经常需要用到DOM4J这样的库来进行解析。当XML文件包含DTD(Document Type Definition)声明时,DOM4J默认会尝试从指定的URL加载DTD文件来进行验证。这通常是为了确保XML文件符合预定的结构和规则。...

    dom4j解析xml详解

    - **配置文件解析**: 许多应用使用XML作为配置文件的格式,DOM4J可以方便地读取和更新这些配置信息。 - **Web服务**: 在SOAP等协议中,XML是常用的数据传输格式,DOM4J能够帮助构建和解析这些XML消息。 - **文档生成...

    java中dom4j读写XML

    **DOM4J的读取XML:** 1. **创建Document对象**:使用`DocumentHelper.parseText()`或`SAXReader.read()`方法解析XML字符串或文件,生成Document对象。 2. **获取Element**:通过Document对象的`rootElement()`方法...

    dom4J解析XML文件

    DOM4J作为一个解析器,它的主要功能包括读取XML文档、遍历XML结构、查找特定元素、修改元素内容以及创建新的XML文档。 首先,解析XML文件通常从构建Document对象开始。在DOM4J中,我们可以使用SAXReader类来实现这...

    dom4j.jar,dom,xml,dom4j

    DOM4J的名字来源于Document Object Model (DOM) 和 Java,它弥补了DOM API在处理大型XML文档时效率低下的问题,并且比DOM更易于使用。 DOM4J的核心概念是Element,它代表XML文档中的一个节点,可以是元素、属性、...

    dom4j_dom4j1.6.1安装包_

    在实际开发中,DOM4J常用于读取配置文件、解析XML格式的数据交换,或者与Web服务交互。由于其优秀的性能和丰富的功能,DOM4J 1.6.1版本至今仍被许多开发者所采用,特别是在那些需要高效处理XML的项目中。 总之,DOM...

    解析xml文件dom4j

    例如,使用DOM4J解析XML文件时,你可以创建`Document`对象,然后通过`DocumentBuilderFactory`和`DocumentBuilder`来读取XML文件。在MySQL数据库操作中,可以创建`Connection`对象,使用`Statement`或`...

    dom4j.jar,java xml

    DOM4J则提供了一种轻量级的替代方案,它不仅支持DOM,还引入了SAX(Simple API for XML)和StAX(Streaming API for XML)的特性,使处理大型XML文件时性能更优。 DOM4J的主要特点包括: 1. **易于使用**:DOM4J的...

    java读取xml文件

    在处理大型 XML 文件时,JAXB 可能不是最佳选择,因为它会将整个 XML 文档加载到内存中。 2. DOM:DOM 是一个 W3C 标准,它提供了一种树形结构来表示整个 XML 文档。通过 DOM,你可以遍历和修改 XML 文档的任何部分...

    dom4j解析XML的两个JAR包(dom4j-1.6.1.jar 和 jaxen.jar)

    2. **SAX和StAX支持**:除了DOM,DOM4J还支持事件驱动的SAX和流式的StAX解析模型,这些模型在处理大型XML文件时特别有用,因为它们不需要将整个文档加载到内存中。 3. **XPath支持**:DOM4J内置了XPath支持,这使得...

    dom4j1.1-1.6.1.rar

    在构建工程时,需要将DOM4J的JAR文件添加到类路径中。提供的"dom4j"文件名可能是解压后的所有文件,其中包括了DOM4J的JAR包和其他相关资源。 总的来说,DOM4J是一个强大且全面的XML处理工具,无论是在小型项目还是...

    使用DOM4J验证DTD最简单的方法

    1. **加载XML文档**:使用DOM4J的`DocumentHelper`类的`parseText()`或`parse()`方法读取XML文档。例如: ```java String xmlContent = "&lt;!DOCTYPE root SYSTEM 'my.dtd'&gt;&lt;root&gt;&lt;element&gt;content&lt;/element&gt;&lt;/root&gt;...

    dom4j-1.6.1.jar

    10. **IO操作**:DOM4J提供了一套简单的API来读写XML文件,支持流式处理,可以高效地处理大文件。 总结来说,DOM4J-1.6.1.jar是一个强大且易用的XML处理库,适合各种Java项目中对XML的读取、修改和创建需求。通过...

    dom4j解析xml例子

    DOM4J是一个强大的Java库,专门用于处理XML文档。它提供了灵活、高性能的方式来解析、创建、修改和操作XML数据。这个“dom4j解析xml例子”压缩包应该包含了一些示例代码、帮助文档和使用说明,旨在帮助初学者快速...

    dom4j源代码,包含dom4j.jar

    DOM4J也支持SAX和DOM解析器,这使得它既可以在内存效率至关重要的情况下使用SAX的事件驱动模型,也可以在处理大型XML文件时选择DOM的完整文档对象模型。此外,DOM4J还提供了XPath支持,允许我们使用简洁的表达式来...

    读取和修改xml文件

    在读取XML文件后,可以通过DOM提供的API进行修改,如`Element`的`setTextContent`、`setAttribute`等方法。修改完成后,需使用`Transformer`将`Document`对象转换回XML字符串,保存到文件。 8. **XPath和XSLT** ...

    读取PLC寄存器,读写XML文件

    2. **读取XML**:通过解析库,我们可以访问XML文件中的节点和属性,提取所需信息。例如,查询特定元素的值或获取整个文档的结构。 3. **写入XML**:创建新的XML文件或修改已有文件涉及添加、删除或更新元素、属性。...

    XML DTD XSL XLD DOM

    总的来说,这些文件涵盖了XML的基础知识,如XML结构、DTD的使用、XSLT转换以及DOM解析,同时也涉及到XML Schema这一高级验证工具。通过学习这些资料,你将能够有效地创建、验证和处理XML文档,以及进行数据的格式...

    dom4j使用简介

    - 在处理大型 XML 文档时,DOM4J 结合 SAX 可以有效地节省内存资源。 5. **DOM4J的应用场景** - Web 开发:用于服务器端 XML 数据的解析和处理,如配置文件的读取和写入。 - 数据交换:在不同系统间通过 XML ...

Global site tag (gtag.js) - Google Analytics