Compilador JAXB XJC sin tener en cuenta mixed=true en documentos de esquema XML
(3)
Después de más investigaciones, no pude hacer nada más que concluir que era un error que archivé. Fue reconocido como JAXB issue # 792 .
XJC parece estar ignorando por completo mixed="true"
en mis elementos de esquema XML y, por lo tanto, no me permite extraer contenido de texto. A partir del ejemplo de XML a continuación, necesito poder extraer "Título de texto". Sin mixed="true"
siendo reconocido, no se crea ningún accessor ni se desasigna de XML:
<?xml version="1.0" encoding="UTF-8"?>
<title xmlns="urn:hl7-org:v3" integrityCheck="true">Title Text</title>
Aquí hay un esquema completo pero minimizado que demuestra el problema:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema targetNamespace="urn:hl7-org:v3"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:hl7-org:v3"
xmlns:mif="urn:hl7-org:v3/mif"
elementFormDefault="qualified">
<xs:complexType name="ST" mixed="true">
<xs:complexContent>
<xs:restriction base="ED">
<xs:sequence>
<xs:element name="reference" type="xs:string" minOccurs="0" maxOccurs="0"/>
<xs:element name="thumbnail" type="xs:string" minOccurs="0" maxOccurs="0"/>
</xs:sequence>
<xs:attribute name="compression" type="xs:string" use="prohibited"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="ED" mixed="true">
<xs:complexContent>
<xs:extension base="BIN">
<xs:sequence>
<xs:element name="reference" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="thumbnail" minOccurs="0" maxOccurs="1" type="xs:string" />
</xs:sequence>
<xs:attribute name="compression" type="xs:string" use="optional" />
<xs:attribute name="integrityCheck" type="xs:string" use="optional" />
<xs:attribute name="integrityCheckAlgorithm" type="xs:string" use="optional" default="SHA-1" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="BIN" abstract="true" mixed="true">
<xs:complexContent>
<xs:extension base="ANY">
<xs:attribute name="representation" use="optional" type="xs:string" default="TXT" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="ANY" abstract="true">
<xs:attribute name="nullFlavor" type="xs:string" use="optional" />
</xs:complexType>
<xs:element name="title" type="ST" />
</xs:schema>
Tenga en cuenta que en el anterior he mixed = "true". A pesar de eso, el fragmento de esquema generado no contiene una referencia a él, ni la clase generada usa la anotación XmlMixed
, ni un acceso de valor o contenido:
/**
* <p>Java class for ST complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="ST">
* <complexContent>
* <restriction base="{urn:hl7-org:v3}ED">
* <sequence>
* <element name="reference" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="0" minOccurs="0"/>
* <element name="thumbnail" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="0" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ST")
public class ST
extends ED
{
}
¿Por qué XJC / JAXB ignora por completo mis campos de contenido mixto? He probado tanto JAXB 2.1 como JAXB 2.2 pero solo existen diferencias triviales en el código generado.
Nota : No puedo cambiar el esquema ya que el esquema real es un esquema de atención médica que cumple con los estándares (HL7).
http://blogs.oracle.com/mgrebac/entry/handling_extended_mixed_content_in
Esto funcionó! Solo crea un archivo vinculante como ese:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings generateMixedExtensions="true"/>
</jaxb:bindings>
Luego use el parámetro -b en la línea de comando de la forma en que generalmente lo hace.
¡Pasan los años, pero este esquema sigue preocupando a la gente! He estado luchando con este mismo XSD (HL7) durante los últimos días, especialmente para manejar los tipos de elementos de contenido mixto.
Mi requisito inicial era el opuesto al del póster original, ya que necesitaba escribir texto simple dentro de un elemento mixto. Pero también debo poder leer dicho contenido, así que apliqué la misma solución sugerida en otra respuesta, que es crear un archivo de enlace personalizado y usarlo en el asistente "Clases de JAXB desde el esquema" de Eclipse. En ese caso, puede elegir específicamente qué archivo (s) de enlace usar en uno de los cuadros de diálogo del asistente.
Como resultado, las clases se generan con un contenido List<Serializable>
siempre que se encuentre un tipo de elemento mixto. Resulta un poco complicado extraer la información que realmente necesita, pero al menos está seguro de que puede acceder mediante programación a todo lo que está presente en un archivo XML que adhiere al XSD.
Incluso puede navegar hacia contenidos mixtos más complejos, como:
<v3:name>
<v3:given>Sample Given Name</v3:given>
<v3:family>Sample Family Name</v3:family>
</v3:name>
Donde el name
se define como tal (eliminé contenido no útil para este ejemplo del XSD original):
<xs:complexType name="EN" mixed="true">
<xs:complexContent>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="delimiter" type="en.delimiter"/>
<xs:element name="family" type="en.family"/>
<xs:element name="given" type="en.given"/>
<xs:element name="prefix" type="en.prefix"/>
<xs:element name="suffix" type="en.suffix"/>
</xs:choice>
</xs:sequence>
</xs:complexContent>
</xs:complexType>
Tipos en.family
, en.given
y such son mixtos (y para nuestro propósito no necesitamos saber nada más).
Entonces, cuando accede al contenido del nombre, su List<Serializable>
estará compuesta por:
- una
String
, siendo los espacios en blanco entre<v3:name>
y<v3:given>
- un elemento
EnGiven
- una
String
, siendo los espacios en blanco entre</v3:given>
y<v3:family>
- un elemento
EnFamily
- una
String
, siendo los espacios en blanco entre</v3:family>
y</v3:name>
EnGiven
y EnFamily
estará compuesto cada uno de un solo String
, respectivamente "Sample Given Name" y "Sample Family Name". De nuevo, es un poco complicado, y probablemente tenga que poner algo de lógica para manejar los casos específicos, pero puede hacerlo de esta manera.
Por cierto, llenar un elemento es trivial: simplemente agregue un String al contenido deseado de la List<Serializable>
.