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

Entradas populares