Soporte de procesadores Java XML
Utilice las funciones de Catálogos XML con los procesadores XML estándar de
Java.
Las características de los catálogos XML se admiten en todos los procesadores
XML de Java, incluidos SAX y DOM (javax.xml.parsers) y analizadores StAX (javax.xml.stream), validación de esquema (javax.xml.validation) y transformación XML (javax.xml.transform).
Esto significa que no es necesario crear un objeto
CatalogResolver fuera de un procesador XML. Los archivos de catálogo se
pueden registrar directamente en el procesador XML de Java, o se pueden
especificar mediante las propiedades del sistema o en el archivo
jaxp.properties. Los
procesadores XML realizan las asignaciones a través de los catálogos de forma
automática.
Habilitar la compatibilidad con catálogos
Para habilitar la compatibilidad con la función de catálogos XML en un
procesador, la función USE_CATALOG debe establecerse en true y debe
especificarse al menos un archivo de entrada de catálogo.
USE_CATALOG
Un procesador XML de Java determina si la función de catálogos XML es
compatible en función del valor de la función USE_CATALOG. De forma
predeterminada, USE_CATALOG se establece en true para todos los
procesadores XML JDK. El procesador XML de Java comprueba además la
disponibilidad de un archivo de catálogo e intenta utilizar la API de catálogo
XML solo cuando la función USE_CATALOG está true y un catálogo está
disponible.
La función USE_CATALOG es compatible con la API del catálogo XML, la
propiedad del sistema y el archivo
jaxp.properties. Por ejemplo,
si USE_CATALOG está configurado en true y es deseable deshabilitar el
soporte de catálogo para un procesador en particular, entonces esto se puede
hacer configurando la función USE_CATALOG a false través del método
setFeature del procesador . El siguiente código establece la
característica USE_CATALOG en el valor especificado
useCatalog para un objeto XMLReader.
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
XMLReader reader = spf.newSAXParser().getXMLReader();
if (setUseCatalog) {
reader.setFeature(XMLConstants.USE_CATALOG, useCatalog);
}
Por otro lado, si todo el entorno debe tener el catálogo desactivado, esto se
puede hacer configurando el archivo
jaxp.properties con una línea:
javax.xml.useCatalog = false;
javax.xml.catalog.files
La propiedad javax.xml.catalog.files está definida por la API del catálogo XML
y es compatible con los procesadores XML de JDK, junto con otras
características del catálogo. Para emplear la función de catálogo en un
proceso de análisis, validación o transformación, todo lo que se necesita es
establecer la propiedad FILES en el procesador, a través de su
propiedad del sistema o utilizando el archivo
jaxp.properties.
URI del catálogo
La referencia del archivo de catálogo debe ser un URI válido, como
file:///users/auser/catalog/catalog.xml.
La referencia de URI en un sistema o una entrada de URI en el archivo de
catálogo puede ser absoluta o relativa. Si son relativos, entonces se
resuelven usando el URI del archivo de catálogo o un URI base si se
especifica.
Uso de entradas del sistema o uri
Cuando se utiliza directamente la API de catálogo XML (ver Interfaces
Catálogo XML API para un ejemplo), las entradas system y uri se utiliza el
soporte nativo XML JDK Procesadores de la clase CatalogFeatures. En
general, las entradas system se buscan primero, luego las entradas public, y
si no se encuentra ninguna coincidencia, el procesador continúa buscando
entradas uri. Debido a que se admiten las entradas system y uri, se
recomienda que siga las especificaciones XML personalizadas al seleccionar
entre usar una entrada system o uri. Por ejemplo, los DTD se definen con un
systemId y, por lo tanto system, son preferibles las entradas.
Usar catálogo con procesadores XML
Utilice la API de catálogo XML con varios procesadores XML de Java.
La API del catálogo XML es compatible con todos los procesadores XML de
JDK. Las siguientes secciones describen cómo se puede habilitar para un
tipo particular de procesador.
Usar catálogo con DOM
Para usar un catálogo con DOM, establezca la propiedad FILES en una
instancia DocumentBuilderFactory como se muestra en el siguiente código:
static final String CATALOG_FILE = CatalogFeatures.Feature.FILES.getPropertyName();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
if (catalog != null) {
dbf.setAttribute(CATALOG_FILE, catalog);
}
Tenga en cuenta que catalog es un URI para un archivo de catálogo. Por
ejemplo, podría ser algo como "file:///users/auser/catalog/catalog.xml".
Es mejor implementar la resolución de archivos de destino junto con el
archivo de entrada de catálogo, de modo que los archivos se puedan resolver
en relación con el archivo de catálogo. Por ejemplo, si lo siguiente es una
entrada uri en el archivo de catálogo, entonces el archivo
XSLImport_html.xsl se
ubicará en /users/auser/catalog/XSLImport_html.xsl.
<uri name="pathto/XSLImport_html.xsl" uri="XSLImport_html.xsl"/>
Usar catálogo con SAX
Para usar la función de catálogo en un analizador SAX, configure el archivo de
catálogo en la instancia SAXParser:
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setXIncludeAware(true);
SAXParser parser = spf.newSAXParser();
parser.setProperty(CATALOG_FILE, catalog);
En el código de muestra anterior, tenga en cuenta la declaración
spf.setXIncludeAware(true).
Cuando esto está habilitado, cualquiera XInclude se resuelve usando el
catálogo también.
Dado un archivo XML XI_simple.xml:
<simple>
<test xmlns:xinclude="http://www.w3.org/2001/XInclude">
<latin1>
<firstElement/>
<xinclude:include href="pathto/XI_text.xml" parse="text"/>
<insideChildren/>
<another>
<deeper>text</deeper>
</another>
</latin1>
<test2>
<xinclude:include href="pathto/XI_test2.xml"/>
</test2>
</test>
</simple>
Además, dado otro archivo XML XI_test2.xml:
<?xml version="1.0"?>
<!-- comment before root -->
<!DOCTYPE red SYSTEM "pathto/XI_red.dtd">
<red xmlns:xinclude="http://www.w3.org/2001/XInclude">
<blue>
<xinclude:include href="pathto/XI_text.xml" parse="text"/>
</blue>
</red>
Suponga que otro archivo de texto XI_text.xml contiene una cadena simple y el
archivo XI_red.dtd es el siguiente:
<!ENTITY red "it is read">
En estos archivos XML, hay un elemento XInclude dentro de un elemento XInclude
y una referencia a un DTD. Suponiendo que estén ubicados en la misma carpeta
junto con el archivo de catálogo CatalogSupport.xml, agregue las siguientes
entradas de catálogo para asignarlos:
<uri name="pathto/XI_text.xml" uri="XI_text.xml"/>
<uri name="pathto/XI_test2.xml" uri="XI_test2.xml"/>
<system systemId="pathto/XI_red.dtd" uri="XI_red.dtd"/>
Cuando parser.parse se llama al método para analizar el archivo XI_simple.xml,
puede ubicar el archivo XI_test2.xml en el archivo XI_simple.xml y el archivo
XI_text.xml y el archivo XI_red.dtd en el archivo XI_test2.xml a través del
catálogo especificado.
Usar catálogo con StAX
Para utilizar la función de catálogo con un analizador StAX, configure el
archivo de catálogo en la instancia XMLInputFactory antes de crear el objeto
XMLStreamReader:
XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog);
XMLStreamReader streamReader =
factory.createXMLStreamReader(xml, new FileInputStream(xml));
Cuando el objeto XMLStreamReader streamReader se utiliza para analizar la
fuente XML, las referencias externas en la fuente se resuelven de acuerdo con
las entradas especificadas en el catálogo.
Tenga en cuenta que, a diferencia de la clase DocumentBuilderFactory que tiene
métodos setFeature y setAttribute, la clase XMLInputFactory define solo un
método setProperty. Las características de la API del catálogo XML incluidas
XMLConstants.USE_CATALOG se configuran mediante este método setProperty. Por
ejemplo, para deshabilitar USE_CATALOG en un objeto XMLStreamReader, puede
hacer lo siguiente:
factory.setProperty(XMLConstants.USE_CATALOG, false);
Usar catálogo con validación de esquema
Para usar un catálogo para resolver cualquier recurso externo en un esquema,
como XSD import e include, configure el catálogo en el objeto
SchemaFactory:
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog);
Schema schema = factory.newSchema(schemaFile);
El documento de esquema XMLSchema contiene referencias a DTD externas:
<!DOCTYPE xs:schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "pathto/XMLSchema.dtd" [
...
]>
Y para importar xsd:
<xs:import
namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2001/pathto/xml.xsd">
<xs:annotation>
<xs:documentation>
Get access to the xml: attribute groups for xml:lang
as declared on 'schema' and 'documentation' below
</xs:documentation>
</xs:annotation>
</xs:import>
Siguiendo este ejemplo, para utilizar recursos locales para mejorar el
rendimiento de su aplicación al reducir las llamadas al servidor W3C:
- Incluya estas entradas en el catálogo establecido en el objeto SchemaFactory:
<public publicId="-//W3C//DTD XMLSCHEMA 200102//EN" uri="XMLSchema.dtd"/>
<!-- XMLSchema.dtd refers to datatypes.dtd -->
<systemSuffix systemIdSuffix="datatypes.dtd" uri="datatypes.dtd"/>
<uri name="http://www.w3.org/2001/pathto/xml.xsd" uri="xml.xsd"/>
- Descargar los archivos de origen XMLSchema.dtd, datatypes.dtdy, xml.xsd y guardarlos junto con el archivo de catálogo.
Como ya se ha comentado, la API del catálogo XML le permite utilizar
cualquiera de los tipos de entrada que prefiera. En el caso anterior, en lugar
de la entrada uri, también podría utilizar cualquiera de los siguientes:
- Una entrada public, porque el atributo namespace en el elemento import se trata como el elemento publicId:
<public publicId="http://www.w3.org/XML/1998/namespace" uri="xml.xsd"/>
- Una entrada system:
<system systemId="http://www.w3.org/2001/pathto/xml.xsd" uri="xml.xsd"/>
Nota: Al experimentar con la API del catálogo XML, puede resultar útil
asegurarse de que ninguno de los URI o ID del sistema utilizados en sus
archivos de muestra apunte a ningún recurso real en Internet, y especialmente
no al servidor W3C. Esto le permite detectar errores temprano en caso de que
falle la resolución del catálogo y evita poner una carga en los servidores
W3C, liberándolos de cualquier conexión innecesaria. Todos los ejemplos de
este tema y otros temas relacionados sobre la API del catálogo XML tienen una
cadena arbitraria "pathto" agregada a cualquier URI para ese propósito, de
modo que ningún URI podría resolverse en un recurso W3C externo.
Para usar el catálogo para resolver cualquier recurso externo en una fuente
XML para ser validado, configure el catálogo en el objeto Validator:
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema();
Validator validator = schema.newValidator();
validator.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog);
StreamSource source = new StreamSource(new File(xml));
validator.validate(source);
Usar catálogo con Transform
Para utilizar la API de catálogo XML en un proceso de transformación XSLT,
configure el archivo de catálogo en el objeto TransformerFactory.
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(CatalogFeatures.Feature.FILES.getPropertyName(), catalog);
Transformer transformer = factory.newTransformer(xslSource);
Si la fuente XSL que utiliza la fábrica para crear el objeto Transformer
contiene DTD, importe e incluya declaraciones similares a estas:
<!DOCTYPE HTMLlat1 SYSTEM "http://openjdk.java.net/xml/catalog/dtd/XSLDTD.dtd">
<xsl:import href="pathto/XSLImport_html.xsl"/>
<xsl:include href="pathto/XSLInclude_header.xsl"/>
Entonces, las siguientes entradas de catálogo se pueden utilizar para resolver estas referencias:
<system
systemId="http://openjdk.java.net/xml/catalog/dtd/XSLDTD.dtd"
uri="XSLDTD.dtd"/>
<uri name="pathto/XSLImport_html.xsl" uri="XSLImport_html.xsl"/>
<uri name="pathto/XSLInclude_header.xsl" uri="XSLInclude_header.xsl"/>
Comentarios
Publicar un comentario