空間站

          北極心空

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

          近日在使用 DOM4J 的時候,遇到一個問題,現在有兩個解決方法,先記下來,以便日后使用。

          問題:對一個 XML 文件進行讀寫操作,但是發現當文件存在的時候,使用DOM4J讀進來的時候,生成的 Document 對象會根據 DTD 里的定義,追加了一些 default 屬性(實際不需要)。而且在讀取的時間被延長。


          有一個 XML 文件如下:

          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 的讀取文件的一般性寫法:

          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>  

          為了不讓生成我們不需要的 default 屬性和縮短文件的操作時間,我們可以調用 SAXReader.setFeature 方法來改變 DOM4J 的行為,片斷代碼如下:

          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

          以下為片斷代碼:

          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 來解決這個問題。

          PS:這個方法是從凝香小筑BLOG的一編主題是:Do not resolve DTD files when dom4j read xml file 的文章里看到的。地址:http://blog.csdn.net/lessoft/archive/2007/06/20/1659579.aspx

          代碼片斷如下:

          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. });  



          完整的代碼如下:

          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. }  
          posted on 2008-07-22 10:03 蘆葦 閱讀(2313) 評論(0)  編輯  收藏 所屬分類: SpringXML
          主站蜘蛛池模板: 瑞金市| 广东省| 安阳市| 区。| 北碚区| 苏尼特左旗| 双牌县| 克拉玛依市| 绥中县| 舞钢市| 绥江县| 米林县| 富蕴县| 安新县| 台北市| 三都| 汉中市| 安顺市| 郓城县| 凭祥市| 都昌县| 曲周县| 巨鹿县| 阳春市| 平南县| 秀山| 怀宁县| 建瓯市| 白山市| 鹿泉市| 兴化市| 阳泉市| 柘城县| 临洮县| 青海省| 定西市| 比如县| 江永县| 庆城县| 华阴市| 长白|