У меня есть одна схема XSD, которая принимает файлы XML, корневым элементом которых является <EnvioBOLETA>
.Таким образом, правильный XML должен выглядеть так:
<EnvioBOLETA version="1.0" ns="..."> <!-- Attributes are irrelevant -->
<SetDte>
<Caratula>
<RutEmisor>11111111-1</RutEmisor>
<RutEnvia>66666666-6</RutEnvia>
<RutReceptor>11111111-1</RutReceptor>
<FchResol>2010-10-10</FchResol>
<NroResol>0</NroResol>
<SubTotDTE>
<TpoDte>39</TpoDte>
<NroDte>1</NroDte>
</SubTotDTE>
</Caratula>
<DTE version="1.0"xmlns:siid="http://www.sii.cl/SiiDte">
<Documento>
<!--Elements with it's attributes-->
</Documento>
<Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<!--DTE's xmlsignature-->
</Signature>
</DTE>
</SetDte>
<Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<!--EnvioBOLETA's xmlsignature-->
</Signature>
</EnvioBOLETA>
Если я использую JAXB, он создаст классы из всей схемы.Получающиеся классы выглядят так:
/* EnvioBOLETA */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"setDTE",
"signature"
})
@XmlRootElement(name = "EnvioBOLETA")
public class EnvioBOLETA {
@XmlElement(name = "SetDTE", required = true)
protected EnvioBOLETA.SetDTE setDTE;
@XmlElement(name = "Signature", namespace = "http://www.w3.org/2000/09/xmldsig#", required = true)
protected SignatureType signature;
@XmlAttribute(name = "version", required = true)
protected BigDecimal version;
/* Getters and Setters */
/* SetDTE*/
public static class SetDTE {
@XmlElement(name = "Caratula", required = true)
protected EnvioBOLETA.SetDTE.Caratula caratula;
@XmlElement(name = "DTE", required = true)
protected List<BOLETADefType> dte;
@XmlAttribute(name = "ID", required = true)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlID
@XmlSchemaType(name = "ID")
protected String id;
/* Getters and Setters and other static classes*/
}
}
/* DTE */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BOLETADefType", propOrder = {
"documento",
"signature"
})
public class BOLETADefType {
@XmlElement(name = "Documento", required = true)
protected BOLETADefType.Documento documento;
@XmlElement(name = "Signature", namespace = "http://www.w3.org/2000/09/xmldsig#", required = true)
protected SignatureType signature;
@XmlAttribute(name = "version", required = true)
protected BigDecimal version;
/* Getters and Setters */
}
Я разрабатываю программу на Java, которая получает файл XML, содержащий только элемент <DTE>
и все внутри него, поскольку остальные теги не требуются.Кроме того, элемент <DTE>
не имеет своей подписи, потому что моя программа должна создать его, используя содержимое элемента <DTE>
, а также содержимое файла PFX и файла PEM (оба эти значения не имеют значения).
Я выполнил следующие шаги для выполнения требования, описанного выше:
- Добавьте аннотацию
@XmlRootElement(name = "DTE")
к классу BOLETADefType
.РЕЗУЛЬТАТ: при попытке отмены вызова входного XML с помощью следующего кода:
JAXBContext context = JAXBContext.newInstance(BOLETADefType.class);
Unmarshaller unMarshaller = context.createUnmarshaller();
InputStream xmlStream = new FileInputStream(args[0]);
Reader xmlReader = new InputStreamReader(xmlStream, "ISO-8859-1");
BOLETADefType dte = (BOLETADefType)unMarshaller.unmarshal(xmlReader);
Выдает следующее исключение:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"DTE"). Expected elements are <{http://www.sii.cl/SiiDte}DTE>
То же, что и первый шаг, но установка пространства имен для пустой строки в аннотации
@XMLRootElement
над определением класса
BOLETADefType
, основанного на решении @dcbyers проблемы в
javax.xml.bind.UnmarshalException: непредвиденный элемент (uri: . То есть:
/* DTE */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "DTE", namespace="")
@XmlType(name = "BOLETADefType", propOrder = {
"documento",
"signature"
})
public class BOLETADefType {
//...
}
РЕЗУЛЬТАТ: Избегает javax.xml.bind.UnmarshalException
, описанного выше, но объект dte
имеет атрибуты documento
и signature
со значением null
.
Аналогично шагу 1, но при создании
Unmarshaller
используется весь пакет вместо класса.Этот шаг основан на решении, заданном @lexicore для проблемы в
Ошибка при неожиданном элементе (uri: "", local: "response").Ожидаемые элементы: <{} quote> JAXBContext context = JAXBContext.newInstance(BOLETADefType.class.getPackage().getName());
РЕЗУЛЬТАТ: Это дает следующее исключение:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"DTE"). Expected elements are <{http://www.sii.cl/SiiDte}DTE>,<{http://www.w3.org/2000/09/xmldsig#}Signature>
То же, что и на шаге 2, но установка пространства имен в аннотации
@XmlType
вместо аннотации
@XmlRootElement
:
/* DTE */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "DTE")
@XmlType(name = "BOLETADefType", namespace="", propOrder = {
"documento",
"signature"
})
public class BOLETADefType {
//...
}
РЕЗУЛЬТАТ: То же, что и шаг 1.
Не используйте аннотацию
@XmlRootElement
, вместо этого определите объект BOLETADefType, как описано на другом сайте:
JAXBElement<BOLETADefType> jaxbElement = (JAXBElement<BOLETADefType>) unMarshaller.unmarshal(new StreamSource(xmlReader), BOLETADefType.class);
BOLETADefType dte = jaxbElement.getValue();
РЕЗУЛЬТАТ: То же, что и шаг 2.
ВОПРОСЫ:
- Есть ли способ отмены маршалинга входного XML-файла, чтобы у объекта
Documento
не было значений null
с использованием JAXB? - Если нет, есть ли способзагрузить XML в объекты без использования библиотеки JDOM, потому что использование этого стало бы моим худшим сценарием?
Заранее спасибо.