Solve different XML Parser conflicts

xiaoxiao2021-03-06  114

At present, XML has been widely used, and we are indispensable to read XML files in the program. Similarly, almost all mainstream applications have to make XML files, this is a problem, due to the reading of XML files The standard is only defined by the interface, and the specific implementation can be implemented by various software vendors. Therefore, there are different versions of the XML Parser interpreter, but the interpreter between different versions is not guaranteed must be compatible, I will Procedures developed under Tomcat, published on Webphere and Oracle 9ias, due to the difference in XML Parser, resulting in the process of running properly, and I summarize the solutions for the following issues.

First, determine how the problem is generated. When we are ready to read an XML file, we will write the following code in our code: SaxParserFactory SPF = javax.xml.Parsers.SaxParserFactory.newInstance (); XmlReader XmlReader = SPF.NEWSAXPARSER .GETXMLREADER ();

When we get XMLReader, you can read the XML file. The problem is that the instance of newinstance () returns to which one XML Parser is implemented? When we go further into the JDK source code, you can find the following Code, (I now explain with JDK 1.4.1 environment), Java will call FactoryFinder.Find method to find the right XML Parser

ClassLoader ClassLoader = FindClassLoader ();

// first check system Property, this attribute is a keyword javax.xml.parsers.SAXParserFactory try {String systemProp = System.getProperty (factoryId); if (! SystemProp = null) {debugPrintln ( "found system property" systemProp) Return newinstance (systemprop, classloader);}} catch (securityException se) {}

/ / Then check $ java.home / lib / xml.properties try {string javah = system.getproperty; string configfile = javah file.separator "lib" file.separator "jaxp. properties "; File f = new File (configFile); if (f.exists ()) {Properties props = new Properties (); props.load (new FileInputStream (f)); String factoryClassName = props.getProperty (factoryId); debugPrintln ( "found java.home property" factoryClassName); return newInstance (factoryClassName, classLoader);}} catch (Exception ex) {if (debug) ex.printStackTrace ();} String serviceId = "META-INF / services / " FactoryID; // Check the service under ClassPath Try {INPUTSTREAM IS = NULL; if (ClassLoader == Null) {IS = ClassLoader.getsystemResourceStream (ServiceID);} else {is = ClassLoader.getreso urceAsStream (serviceId);} if (is = null!) {debugPrintln ( "found" serviceId); BufferedReader rd = new BufferedReader (new InputStreamReader (is, "UTF-8")); String factoryClassName = rd.readLine () Rd.close ();

if (factoryClassName = null && "!!" .equals (factoryClassName)) {debugPrintln ( "loaded from services:" factoryClassName); return newInstance (factoryClassName, classLoader);}}} catch (Exception ex) {if (debug) ex.printStackTrace ();} // last attempt to instantiate a default XML Parser: org.apache.crimson.jaxp.SAXParserFactoryImpl if (fallbackClassName == null) {throw new ConfigurationError ( "Provider for" factoryId "can not be found ", null); debugprintln (" loaded from Fallback Value: " FallbackClassName); Return NewInstance (FallbackClassName, ClassLoader);

Now we should understand how Java loaded XML Parser, when we found that the system automatically loaded XML Parser can set the XML Parsersystem.getProperties we want to use with the following code, you can use the following code. ) .SETPROPERTY ("javax.xml.parsers.saxparserfactory", "What you need XML Parser");

However, it should be noted that this is a global setting, which uses the XML Parser settings of the entire system to use the Parser you defined, which is likely to affect the operation of other code, maybe you can also need you need Perform system.getProperties (). SetProperty ("javax.xml.parsers.saxparserfactory", "What you need XML Parser"); after the code is executed, you will perform setProperty again ("javax.xml.parsers.saxparserfactory" "Restore the original value"); but this will have another problem, that is, you can't guarantee the line between the thread is safe, so this method is suitable for use when you want to use global replacement.

Another method, more direct, is to create an XML Parser instance you need, the original way is like this: saxparserfactory spf = javax.xml.parsers.saxparserfactory.newinstance (); now a little SAXPARSERFAACTORY SPF = New ORG .apache.xalan.Processor.TransformerFactoryImpl (); this should be good, how to load XML Parser and you have nothing to do :), but this is not a great design, so my suggestion is to package a Factory class. This way you can use the XML Parser you want.

转载请注明原文地址:https://www.9cbs.com/read-102981.html

New Post(0)