没有空格的XML属性

时间:2011-12-16 05:14:57

标签: java xml xml-serialization jaxb

我使用JAXB为以下模式创建了一个类(在webservice中使用):

<xs:complexType name="ExceptionType">
        <xs:attribute name="errorCode" type="xs:positiveInteger" use="required"/>
        <xs:attribute name="outcomeType" use="required">
            <xs:simpleType>
                <xs:restriction base="xs:token">
                    <xs:enumeration value="rejectFile"/>
                    <xs:enumeration value="rejectSubmission"/>
                    <xs:enumeration value="continue"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
</xs:complexType>

虽然他们发送的实际XML是

<Exception errorCode="1503"outcomeType="continue">

(没有“1503”和outcomeType的空格)。

现在,我将整个XML响应中的<Exception errorCode="(\d*)"outcomeType替换为<Exception errorCode="\1" outcomeType,然后将其提供给JAXB unmarshaller并且它可以工作,但我想知道其他一些XML响应是否会出现这个“错误” 。
JAXB是否有更简单的方法接受带有此attr1="value"attr2错误的XML标记?或者可能使用一些自定义的XMLFilterImpl?

3 个答案:

答案 0 :(得分:3)

  

JAXB是否有更简单的方法接受带有此attr1 =“value”attr2错误的XML标记?

不,因为这不是错误。

包含attr1="value"attr2的XML格式不正确,因此JAXB无法对其进行解析,并将抛出异常,指示致命的,不可恢复的错误。

如果您希望 XML-ish 此类数据并且您无法控制它(您从第三方接收它),那么您的解决方案似乎确定。但是,如果我是你,我会联系这个第三方并告诉他们他们正在宣传无效的XML并且这不太专业。

用正则表达式替换字符串的替代方法可能是这样的(但这并不容易):

public String toWellFormed(String xml) throws IOException, SAXException {             
  StringBuilder sb = new StringBuilder(xml);                                                 

  XMLReader reader = XMLReaderFactory.createXMLReader();                                     
  reader.setContentHandler(null);                                                            
  reader.setErrorHandler(null);                                                              

  boolean threw = true;                                                                      
  while (threw)                                                                              
    try {                                                                                    
      reader.parse(new InputSource(new StringReader(sb.toString())));                        
      threw = false;                                                                         
    } catch (SAXParseException ex) {                                                         
      if (ex.getMessage().contains("must be followed by either attribute specifications")) {
        threw = true;
        int line = ex.getLineNumber();                                                       
        int column = ex.getColumnNumber();                                                   
        sb.insert(line * column - 1, ' ');                                                                                                            
      } else                                                                                 
        throw ex;                                                                            
    }                                                                                        

  return sb.toString();                                                                      
}                       

String malformedXml = "<test a='a'b='b'c='c'/>";  
String wellFormedXml = toWellFormed(malformedXml);
"<test a='a'b='b'c='c'/>".equals(wellFormedXml);

JAXB的Unmarshaller应该能够在此过程之后处理wellFormedXml

如果用正则表达式替换东西是足够好的,因为你的数据不包含太多搜索内容并且只包含你所描述的特定格式错误,那么当然不要使用我的解决方案,但如果你期望更多的格式错误,你可以使用这样的东西。

请注意,我明确将读者的错误和内容处理程序设置为null。这是因为如果格式错误的XML,它们永远不会被调用;读者会尽早失败,因为这是一个致命的,不可恢复的错误。这对我们来说当然非常糟糕,因为如果文档包含10个错误,就像你所描述的那样,那么我的方法会解析XML 10次,直到找到每个错误。我不知道JDK中的XML解析器会报告格式错误并继续解析(报告过程中的每个错误)。

使用正确的 ErrorHandler您可以优雅地处理警告和错误,但即使使用ErrorHandler,也无法处理致命错误调用其fatalError方法,处理停止)。

使用XMLFilter实现也无济于事,因为如果您只是使用默认的XMLFilterImpl类将其所有调用转发给代理XMLReader,那么您将面临与以前相同的问题:在第一个错误,处理停止。事实上,如果你想实现某些东西,那么直接实现XMLReader界面(XMLFilter只会添加setParentgetParent方法 - 糟糕的设计我)。但实现一个可以解析格式错误的XML的XMLReader可能会很乏味。

答案 1 :(得分:1)

这是一个无效的xml(attr值和下一个attr之间没有空格),解析器总是会失败。我认为你必须按照目前的方式管理它,或者在源代码中纠正它。

答案 2 :(得分:0)

好吧,JAXB只是遵循XML的约束。如果没有空间,它将无法验证。也许关闭验证?它可能会通过它。