在工作中,我們剛剛將舊的web應用程序從struts 1.1遷移到1.2.9(希望首先轉移到1.3),但我們現在在普通消化器方面有問題。 Struts 1.2.9使用commons-digester 1.6。SAXParseException:'屬性'「綁定到名稱空間」null「已經爲元素」metric「指定'
當我們試圖分析我們的XML文件中的一個,我們得到異常:
org.xml.sax.SAXParseException: Attribute "" bound to namespace "null" was already specified for element "metric".
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:232)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:213)
at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:385)
at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:315)
at org.apache.xerces.impl.dtd.XMLNSDTDValidator.startNamespaceScope(XMLNSDTDValidator.java:242)
at org.apache.xerces.impl.dtd.XMLDTDValidator.handleStartElement(XMLDTDValidator.java:1980)
at org.apache.xerces.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:802)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:313)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(XMLNSDocumentScannerImpl.java:610)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1608)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:346)
at org.apache.xerces.parsers.DTDConfiguration.parse(DTDConfiguration.java:529)
at org.apache.xerces.parsers.DTDConfiguration.parse(DTDConfiguration.java:585)
at org.apache.xerces.parsers.XMLParser.parse(XMLParser.java:152)
at org.apache.xerces.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1142)
at org.apache.commons.digester.Digester.parse(Digester.java:1572)
at com.foo.ctms.framework.metrics.parser.MetricsXMLParser$InternalDigester.parse(MetricsXMLParser.java:54)
at com.foo.ctms.framework.metrics.parser.MetricsXMLParser.parse(MetricsXMLParser.java:40)
在調查這個問題,我試圖讓一個簡單可行的情況下,這就是我目前有:
package com.foo.ctms.framework.metrics.parser;
import org.apache.commons.digester.Digester;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.net.URL;
/**
* Class that provides methods for parsing metrics definitions defined via XML and populating an object graph of JavaBeans
* representing the definition.
* @version $Revision: 41470 $
*/
public final class MetricsXMLParser {
/**
* The set of public identifiers, and corresponding resource names, for the versions of the configuration file DTD that we know
* about. The key is the name of the resource as in the XMl file, and the value is the location of the resource with respect to
* the <code>ClassLoader</code> that this code in running in.
*/
private static final String registrations[] = {"-//Foo Inc.//DTD Portal Metrics 1.0//EN", "metrics.dtd"};
private MetricsXMLParser() {
}
/**
* Parses a metric definition specified as an <code>InputStream</code>.
* @param url The metrics definition to parse. Must not be <code>null</code>.
* @throws IOException if an I/O error occured while attempting to parse
* @throws SAXException if an XML parsing error occured
*/
public static MetricDefinition parse(URL url)
throws IOException, SAXException {
InternalDigester digester = new InternalDigester();
return digester.parse(url);
}
private static final class InternalDigester {
private final Digester digester;
/**
* Parses a metric definition specified as an <code>InputStream</code>.
* @param input The metrics definition to parse. Must not be <code>null</code>.
* @throws IOException if an I/O error occured while attempting to parse
* @throws SAXException if an XML parsing error occured
*/
public MetricDefinition parse(URL input)
throws IOException, SAXException {
return (MetricDefinition)digester.parse(new InputSource(input.toString()));
}
private InternalDigester() {
digester = new Digester();
digester.setValidating(true);
for (int i = 0; i < MetricsXMLParser.registrations.length; i += 2) {
URL url = getClass().getResource(MetricsXMLParser.registrations[i + 1]);
if (url != null) {
digester.register(MetricsXMLParser.registrations[i], url.toString());
}
}
digester.addObjectCreate("metric", MetricDefinition.class);
digester.addSetProperties("metric");
}
}
}
其給出XML:
<?xml version='1.0' encoding='windows-1252'?>
<!DOCTYPE metric PUBLIC "-//Foo Inc.//DTD Portal Metrics 1.0//EN" "metrics.dtd">
<metric name="metricsConfig" defaultView="trials">
</metric>
DTD是目前下降到:
<!-- A metric element is the document root -->
<!ELEMENT metric ANY>
<!-- A metric has a name and a default view. The default view must
exactly match the name of one of the nested views -->
<!ATTLIST metric
name CDATA #REQUIRED
defaultView CDATA #IMPLIED
>
有沒有人知道我在做什麼錯?
如果我刪除defaultView屬性,我不會收到錯誤。
按sfussenegger的建議,我現在已經嘗試了以下(非沼氣池)代碼:
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(true);
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
reader.parse(new InputSource(url.toString()));
} catch (Exception e) {
e.printStackTrace();
}
,無法生育的問題,而是添加以下(其中公共沼氣池還確實在XercesParser)之前,使用我廠提供了同樣的異常:
factory.setFeature("http://apache.org/xml/features/validation/dynamic", true);
factory.setFeature("http://apache.org/xml/features/validation/schema", true);
在我們決定嘗試Xerces的更現代的版本(2.7.1)結束,這似乎工作。
難道你不能刪除公共沼氣池重現問題?看起來異常是完全解析相關的。因此,對於普通的SAX解析應該是一樣的。 – sfussenegger 2009-10-23 10:11:34