2011-12-16 2 views
0

я использовал JAXB, чтобы создать класс для следующей схемы (используется в веб-сервиса):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» и resultType).

Прямо сейчас, я заменяю <Exception errorCode="(\d*)"outcomeType на весь ответ XML, прежде чем подавать его на unmarshaller JAXB, и он работает, но мне интересно, будет ли в некоторых других ответах XML эта «ошибка».
Есть ли более простой способ, чтобы JAXB принимал XML-теги с этой ошибкой attr1="value"attr2? Или, может быть, с помощью некоторого пользовательского XMLFilterImpl?

ответ

3

Есть ли более простой способ, чтобы JAXB принимал XML-теги с этим атрибутом attr1 = "value" attr2?

Нет, потому что это не ошибка.

XML, содержащий attr1="value"attr2, не имеет правильной формы, поэтому JAXB не может его разобрать и выдаст исключение, указывающее фатальную, невосстановимую ошибку.

Если вы ожидаете XML-иш данные такого рода, и вы не имеете никакого контроля над ним (вы получите его от третьих лиц), то ваше решения кажется 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 раз, пока не обнаружит каждую ошибку. Я не знаю анализатора XML в JDK, который бы сообщал о ошибках форматирования и продолжал синтаксический анализ (сообщая о каждой ошибке во время процесса).

Использование надлежащегоErrorHandler вы могли бы обрабатывать предупреждения и ошибки грациозно, однако фатальные ошибки не могут быть обработаны даже с ErrorHandler (после того, как его метод fatalError вызывается, обработка прекращается).

Использование XMLFilter реализации не поможет вам либо, потому что если вы просто использовать XMLFilterImpl класс по умолчанию, который направляет все свои вызовы делегата XMLReader, то вы бы столкнуться с той же проблемой, как и раньше: на первой ошибки, обработка останавливается. На самом деле, если вы хотите что-то реализовать, тогда реализуйте интерфейс XMLReader напрямую (XMLFilter добавляет только методи getParent, если вы спросите меня). Но реализация XMLReader, которая может анализировать искаженный XML, вероятно, будет утомительной.

+0

Я соглашусь с этим как ответом, так как он лучше обходной путь, чем мой текущий. Хотя я не буду использовать его, поскольку текущий поток содержит несколько документов XML, и у меня уже есть собственный фильтр, чтобы разделить их, чтобы JAXB обрабатывал их правильно, что приводит к неправильным номерам строк и столбцов. Кроме того, может быть несколько элементов ExceptionType, все из которых содержат эту ошибку, для чего потребуется цикл, чтобы исправить все из них, что является большим хитом производительности по сравнению с просто заменой каждого совпадения. Благодаря! –

1

Это недопустимый xml (без пробела между значением attr и следующим attr), и парсер всегда будет терпеть неудачу. Я думаю, вам придется управлять им так, как вы сейчас делаете, или же исправлять его в самом источнике.

+0

Исправление источника было первой попыткой, которую я сделал, так как казалось, что они были бы благодарны за исправление такой ошибки, но они отказались признать это, поэтому мне нужно исправить-до-разбора. Я надеялся, что это будет несколько распространено и найти какое-то обходное решение в Интернете, но ничего .. –

0

Ну, JAXB просто следует ограничениям XML. Если нет места, он не будет проверяться. Может быть, отключить проверку? Это может сработать.

+1

не думаю, что это связано с проверкой, его искаженным xml, который здесь является проблемой – Nrj