saxparseexception : 'attribute' '는 네임 스페이스 "null"에 바운드 "메트릭"에 이미 지정되었습니다.

StackOverflow https://stackoverflow.com/questions/1612411

문제

직장에서, 우리는 오래된 웹 애플을 Struts 1.1에서 1.2.9에서 마이그레이션했지만 (1.3으로 이동하기위한 첫 번째 단계), 이제 Commons 소화기에 문제가 있습니다. Struts 1.2.9는 Commons Digester 1.6을 사용합니다.

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에서 Commons-Digester도 수행하는 Commons-Digester도 추가)를 추가하면 동일한 예외가됩니다.

factory.setFeature("http://apache.org/xml/features/validation/dynamic", true);
factory.setFeature("http://apache.org/xml/features/validation/schema", true);

결국 우리는보다 현대적인 버전의 Xerces (2.7.1)를 시험해보기로 결정했으며 그것은 효과가있는 것 같습니다.

도움이 되었습니까?

해결책

문제는 Commons-Digester 1.6과 Xerces (Xercesparser에서 2.2) 사이의 비 호환성으로 인해 발생한 것으로 보이며, 최근 버전의 Xerces (2.7.1)로 이동하면 문제가 해결되었습니다.

우리는이 버전의 라이브러리를 선택했습니다. 우리가 가지고있는 다른 웹 응용 프로그램이 이미 사용하고 있기 때문입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top