2011-12-16 69 views
0

我使用JAXB创建以下架构类(在Web服务中使用):XML属性没有空格

<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的空格)。

现在,我与<Exception errorCode="\1" outcomeType整个XML响应更换<Exception errorCode="(\d*)"outcomeType将其送入JAXB解组之前和它的作品,但我不知道一些其他的XML响应都会有这样的“错误”。
有没有更简单的方法让JAXB接受这个attr1="value"attr2错误的XML标签?或者也许使用一些自定义的XMLFilterImpl?

回答

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可能会很乏味。

+0

我会接受这一个作为答案,因为它是一个更好解决方法比我目前的一个。尽管我不会使用它,因为当前流包含多个XML文档,并且我已经有了一个自定义过滤器来将它们分开,以便JAXB正确处理它们,从而导致错误的行和列号。另外,可能有多个ExceptionType元素,都包含这个bug,这需要一个循环来修复所有这些,这是一个很大的性能影响,而不是快速替换每个匹配。谢谢! – 2011-12-19 17:17:30

1

这是一个无效的XML(attr值和下一个attr之间没有空格),解析器总是失败。我认为你将不得不按照你现在正在做的方式来管理它,否则就在源代码中纠正它。

+0

更正源代码是我做的第一次尝试,因为它似乎很乐意修复此类错误,但他们拒绝承认它,所以我必须在解析之前进行修复。我希望这会有点普遍,并找到一些解决方法在线,但没有.. – 2011-12-16 09:03:07

0

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

+1

不认为其相关的验证,其格式错误的XML这是这里的问题 – Nrj 2011-12-16 05:49:58