con - validar xml vs xsd
xmllint: validar un archivo XML contra dos esquemas XSD(sobre/carga Ăștil) (3)
Estoy usando xmllint para hacer algunas validaciones y tengo un documento de instancia XML que necesita validar contra dos esquemas: uno para el "sobre" externo (que incluye un elemento cualquiera ) y otro para la carga útil particular. Diga A.xsd es el esquema de envolvente, B.xsd un esquema de carga útil (hay diferentes cargas útiles posibles) y ab.xml un documento de instancia XML válido (proporciono un ejemplo al final de la publicación).
Tengo los tres archivos localmente disponibles en el mismo directorio y estoy usando xmllint para realizar la validación, proporcionando como argumento del esquema la ubicación del esquema externo (sobre):
xmllint -schema A.xsd ab.xml
... aún así, aunque proporciono la ubicación de A.xsd y B.xsd en el documento de instancia (utilizando el elemento xsi: schemaLocation ), xmllint no puede encontrarlo y se queja:
ab.xml:8: element person: Schemas validity error : Element ''{http://www.example.org/B}person'': No matching global element declaration available, but demanded by the strict wildcard.
ab.xml fails to validate
Entonces, aparentemente xmllint no está leyendo el elemento xsi: schemaLocation . Entiendo que xmllint se puede configurar con catálogos pero no logré que xmllint encuentre ambos esquemas. ¿Cómo debería obtener xmllint para tener en cuenta ambos esquemas al validar el documento de instancia o hay otra utilidad de línea de comandos o herramienta gráfica que podría usar en su lugar?
SSCCE
A.xsd - esquema del sobre
<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified"
xmlns ="http://www.w3.org/2001/XMLSchema"
xmlns:a ="http://www.example.org/A"
targetNamespace ="http://www.example.org/A">
<element name="someType" type="a:SomeType"></element>
<complexType name="SomeType">
<sequence>
<any namespace="##other" processContents="strict"/>
</sequence>
</complexType>
</schema>
B.xsd - esquema de carga útil
<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified"
xmlns ="http://www.w3.org/2001/XMLSchema"
xmlns:b ="http://www.example.org/B"
targetNamespace="http://www.example.org/B"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<element name="person" type="b:PersonType"></element>
<complexType name="PersonType">
<sequence>
<element name="firstName" type="string"/>
<element name="lastName" type="string"/>
</sequence>
</complexType>
</schema>
ab.xml - documento de instancia
<?xml version="1.0" encoding="UTF-8"?>
<a:someType xmlns:a="http://www.example.org/A"
xmlns:b="http://www.example.org/B"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/A A.xsd
http://www.example.org/B B.xsd">
<b:person>
<b:firstName>Mary</b:firstName>
<b:lastName>Bones</b:lastName>
</b:person>
</a:someType>
Dejé de usar xmllint y usé Xerces en su lugar.
Descargué el tarball de Xerces y, después de explotarlo en una carpeta local, creé el siguiente script de validación (basado en esta sugerencia ):
#!/bin/bash
XERCES_HOME=~/software-downloads/xerces-2_11_0/
echo $XERCES_HOME
java -classpath $XERCES_HOME/xercesImpl.jar:$XERCES_HOME/xml-apis.jar:$XERCES_HOME/xercesSamples.jar sax.Counter $*
El archivo ab.xml se valida luego, contra ambos esquemas, con el siguiente comando:
validate -v -n -np -s -f ab.xml
Xerces está leyendo las ubicaciones de esquema del elemento xsi: schemaLocation en ab.xml, por lo que no es necesario que se proporcionen en la invocación de línea de comando.
Si tenía un elemento de import
en su A.xsd
, justo después de abrir la etiqueta de schema
,
<xsd:import namespace="http://www.example.org/B" schemaLocation="B.xsd"/>
entonces podrías pasar A.xsd
a xmllint
y funcionaría con:
xmllint -schema A.xsd ab.xml
Puede crear un esquema de contenedor e importar ambos espacios de nombres. AB.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://www.example.org/A" schemaLocation="A.xsd"/>
<import namespace="http://www.example.org/B" schemaLocation="B.xsd"/>
</schema>
Entonces:
xmllint --schema AB.xsd ab.xml
<?xml version="1.0" encoding="UTF-8"?>
<a:someType xmlns:a="http://www.example.org/A" xmlns:b="http://www.example.org/B" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/A A.xsd http://www.example.org/B B.xsd">
<b:person>
<b:firstName>Mary</b:firstName>
<b:lastName>Bones</b:lastName>
</b:person>
</a:someType>
ab.xml validates