【问题标题】:XML attributes without spaces没有空格的 XML 属性
【发布时间】:2011-12-16 05:14:56
【问题描述】:

我已经使用 JAXB 为以下架构创建了一个类(用于 web 服务):

<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”和结果类型)。

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

【问题讨论】:

    标签: java xml xml-serialization jaxb


    【解决方案1】:

    有没有更简单的方法让 JAXB 接受带有这个 attr1="value"attr2 错误的 XML 标记?

    不,因为这不是错误。

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

    如果您期望 XML-ish 这类数据并且您无法控制它(您从第三方收到它),那么您的解决方案似乎 OK。但是,如果我是你,我会联系这个第三方并告诉他们他们正在喷出无效的 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 解析器,它会报告格式错误并继续解析(报告过程中的每个错误)。

    使用 proper ErrorHandler 您可以优雅地处理警告和错误,但是即使使用 ErrorHandler(在其 fatalError 之后)也无法处理 致命错误方法被调用,处理停止)。

    使用XMLFilter 实现也对您没有帮助,因为如果您只是使用默认的XMLFilterImpl 类将其所有调用转发给委托XMLReader,那么您将面临与以前相同的问题:第一个错误,处理停止。事实上,如果你想实现一些东西,那么直接实现XMLReader接口(@98​​7654333@只添加了setParentgetParent方法——如果你问我这是不好的设计)。但是实现一个可以解析格式错误的 XML 的 XMLReader 可能会很乏味。

    【讨论】:

    • 我会接受这个作为答案,因为它比我目前的解决方法更好。虽然我不会使用它,因为当前流包含多个 XML 文档,并且我已经有一个自定义过滤器来拆分它们,以便 JAXB 正确处理它们,从而导致错误的行号和列号。另外,可能有多个 ExceptionType 元素,都包含这个错误,这将需要一个循环来修复所有这些错误,与快速替换每个匹配项相比,这是一个很大的性能损失。谢谢!
    【解决方案2】:

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

    【讨论】:

    • 纠正源代码是我做的第一次尝试,因为他们似乎会感谢修复这样的错误,但他们拒绝承认,所以我必须先修复再解析。我希望这会有点普遍,并在网上找到一些解决方法,但没有..
    【解决方案3】:

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

    【讨论】:

    • 不要认为它与验证有关,这里的问题是格式错误的 xml
    猜你喜欢
    • 2011-01-17
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多