2009-07-11 11 views
4

некоторые фрагменты кода.проверка JAXB, но whitespace не игнорируется

java кодирование делает jaxb unmarshaling. довольно простой, скопированный из учебников онлайн.

JAXBContext jc = JAXBContext.newInstance("xmlreadtest"); 
Unmarshaller u = jc.createUnmarshaller(); 

// setting up for validation. 
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
StreamSource schemaSource = new StreamSource(ReadXml.class.getResource("level.xsd").getFile()); 
Schema schema = schemaFactory.newSchema(schemaSource); 
u.setSchema(schema); 

// parsing the xml 
URL url = ReadXml.class.getResource("level.xml"); 
Source sourceRoot = (Source)u.unmarshal(url); 

Элемент проблемы из файла xml. Элемент содержит ничего, кроме невежественных пробелов. Его плохо сформированный, как показано на рисунке точно, как его найдено в файле.

<HashLine _id='FI6' 
ppLine='1' 
origLine='1' 
origFname='level.cpp'> 
</HashLine> 

Элемент xsd, который описал этот элемент.

<xs:element name="HashLine"> 
    <xs:complexType> 
    <xs:attribute name="origLine" type="xs:NMTOKEN" use="required" /> 
    <xs:attribute name="origFname" type="xs:string" use="required" /> 
    <xs:attribute name="_id" type="xs:ID" use="required" /> 
    <xs:attribute name="ppLine" type="xs:NMTOKEN" use="required" /> 
    </xs:complexType> 
</xs:element> 

ошибка

[org.xml.sax.SAXParseException: cvc-complex-type.2.1: Element 'HashLine' must have no character or element information item [children], because the type's content type is empty.] 

Я проверил ошибка исходит из этого элемента.

Он загружается отлично без проверки. Но мне нужно использовать валидацию, поскольку я буду делать большие изменения и дополнения к приложению, и я должен быть уверен в том, что все будет должным образом обработано или несогласовано.

Он также отлично работает, если я изменяю complexType, чтобы включить simpleContext с расширением xs: string. Но я получаю эту проблему от сущностей по всему миру, из которых есть alot, amd в alot xsd-файлов. Поэтому нецелесообразно основывать каждый элемент в XML-документах на xs: string, чтобы обойти эту проблему.

Событие, хотя j2se 6 использует SchemaFactory из apache-xerces, похоже, что он не принимает функцию «игнорировать-пробел» от xerces. (Т.е. schemaFactory.setFeature())

ответ

4

Вы можете использовать StAX API отфильтровать пустые блоки символов до проверки используя EventFilter:

class WhitespaceFilter implements EventFilter { 
    @Override 
    public boolean accept(XMLEvent event) { 
    return !(event.isCharacters() && ((Characters) event) 
     .isWhiteSpace()); 
    } 
} 

Это может использоваться, чтобы обернуть ввод:

// strip unwanted whitespace 
XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
XMLEventReader eventReader = inputFactory 
    .createXMLEventReader(ReadXml.class.getResourceAsStream("level.xml")); 
eventReader = inputFactory.createFilteredReader(eventReader, 
    new WhitespaceFilter()); 

// parsing the xml 
Source sourceRoot = (Source) unmarshaller.unmarshal(eventReader); 

//TODO: proper error + stream handling 
2

Я бы предложил написать очень простое преобразование XSLT, чтобы вырезать пустое содержимое из тех конкретных элементов, которые вызывают проблему (например, только элементы HashLine). Затем поставьте шаг обработки перед передачей данных через JAXB, используя TransformerFactory, Transformer и т. Д., Который «очищает» данные с помощью преобразования XSLT. В XSLT можно добавить сортировку логики очистки для случаев, когда в исходном XML вы найдете другие дружественные структуры, отличные от JAXB.

+0

Я не думаю, что это так много, что документ не является дружественным JAXB, так как он не подходит для проверки. Вероятно, вы правы, что лучше ориентироваться на определенные элементы. Я предполагаю, что вы могли бы сделать что-то подобное с DOM/XPath, но это было бы не так элегантно, как использование XSLT. – McDowell

+0

Да, я думаю, что декларативный подход никогда не будет чем-то императивным в этом случае. Если ваши XML-документы не соответствуют схеме, вам необходимо исправить это до передачи через валидатор. XSLT хорош в этом. – skaffman

+0

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