XMLプロセッサでのカタログの使用

XMLカタログAPIを様々なJava XMLプロセッサで使用します。

XMLカタログAPIはすべてのJDK XMLプロセッサでサポートされます。次の項では、特定のタイプのプロセッサでこれを有効化する方法について説明します。

DOMでのカタログの使用

DOMでカタログを使用するには、次のコードで示すように、DocumentBuilderFactoryインスタンスにFILESプロパティを設定します。

static final String CATALOG_FILE = CatalogFeatures.Feature.FILES.getPropertyName();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
if (catalog != null) {
   dbf.setAttribute(CATALOG_FILE, catalog);
}

catalogはカタログ・ファイルへのURIであることに注意してください。たとえば、"file:///users/auser/catalog/catalog.xml"のようになります。

解決対象のファイルとともにカタログ・エントリ・ファイルをデプロイするのが最良の方法であり、こうすることでファイルはカタログ・ファイルに対して相対的に解決されます。たとえば、カタログ・ファイルのuriエントリが次に示すようになっている場合、XSLImport_html.xslファイルは/users/auser/catalog/XSLImport_html.xslにあります。

<uri name="pathto/XSLImport_html.xsl" uri="XSLImport_html.xsl"/>

SAXでのカタログの使用

SAXパーサーでカタログ機能を使用するには、カタログ・ファイルをSAXParserインスタンスに設定します。

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setXIncludeAware(true);
SAXParser parser = spf.newSAXParser();
parser.setProperty(CATALOG_FILE, catalog);

前述のサンプル・コードの文spf.setXIncludeAware(true)に注意してください。これが有効になっていると、XIncludeも同様にカタログを使用して解決されます。

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>

さらに、別の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>

別のテキスト・ファイルXI_text.xmlに単純な文字列が含まれており、ファイルXI_red.dtdが次のようであるとします。

 <!ENTITY red "it is read">

これらのXMLファイルにはXInclude要素の中にXInclude要素が含まれており、DTDへの参照があります。これらがカタログ・ファイルCatalogSupport.xmlとともに同じフォルダ内にある場合は、これらをマップするために次のカタログ・エントリを追加します。

<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"/>

XI_simple.xmlファイルを解析するためにparser.parseメソッドがコールされると、指定されたカタログを使用して、XI_simple.xmlファイルの中のXI_test2.xmlを見つけることができ、XI_test2.xmlファイルの中のXI_text.xmlファイルとXI_red.dtdファイルを見つけることができます。

StAXでのカタログの使用

StAXパーサーでカタログ機能を使用するには、XMLStreamReaderオブジェクトを作成する前に、カタログ・ファイルをXMLInputFactoryインスタンスに設定します。

XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog);
XMLStreamReader streamReader =
  factory.createXMLStreamReader(xml, new FileInputStream(xml));

XMLソースの解析にXMLStreamReader streamReaderオブジェクトを使用すると、ソースの外部参照はカタログに指定されているエントリに従って解決されます。

setFeatureメソッドとsetAttributeメソッドの両方を持っているDocumentBuilderFactoryクラスとは異なり、XMLInputFactoryではsetPropertyメソッドのみが定義されることに注意してください。XMLConstants.USE_CATALOGを含むXMLカタログAPIはすべて、このsetPropertyメソッドを使用して設定されます。たとえば、XMLStreamReaderオブジェクトでUSE_CATALOGを無効化するには、次のようにします。

factory.setProperty(XMLConstants.USE_CATALOG, false);

スキーマ検証でのカタログの使用

カタログを使用してスキーマ内の外部リソースを解決するには(XSD importおよびincludeなど)、SchemaFactoryオブジェクトにカタログを設定します。

SchemaFactory factory =
  SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog);
Schema schema = factory.newSchema(schemaFile);

XMLSchemaスキーマ・ドキュメントには外部DTDへの参照が含まれています。

<!DOCTYPE xs:schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "pathto/XMLSchema.dtd" [
   ... 
]>

および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>

この例に従ってローカル・リソースを使用すると、W3Cサーバーへのコールが減ることによってアプリケーションのパフォーマンスが改善します。

  • 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"/>
  • XMLSchema.dtddatatypes.dtdおよびxml.xsdのソース・ファイルをダウンロードし、カタログ・ファイルとともに保存します。

前述のとおり、XMLカタログAPIでは任意のエントリ・タイプを使用できます。前述のケースでは、uriエントリのかわりに次のいずれかを使用できます。

  • publicエントリ。import要素のnamespace属性がpublicId要素として扱われるためです。

<public publicId="http://www.w3.org/XML/1998/namespace" uri="xml.xsd"/>
  • systemエントリ。

<system systemId="http://www.w3.org/2001/pathto/xml.xsd" uri="xml.xsd"/>

ノート:

XMLカタログAPIを使用したテストでは、サンプル・ファイルで使用されるURIまたはシステムIDが、インターネット上にある実際のリソース(特にW3Cサーバー)をポイントしていないことを確認してください。これによって、カタログの解決の失敗を早期に発見でき、W3Cサーバーに負荷をかけることなく、不要な接続を防ぐことができます。そのため、このトピックおよびXMLカタログAPIに関係するその他のトピックでは、すべての例のURIに恣意的な文字列"pathto"が追加されており、URIが外部のW3Cリソースに解決されないようにしています。

カタログを使用して検証対象のXMLソースの外部リソースを解決するには: 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);

変換でのカタログの使用

XSLT変換プロセスでXMLカタログAPIを使用するには、TransformerFactoryオブジェクトにカタログ・ファイルを設定します。

TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(CatalogFeatures.Feature.FILES.getPropertyName(), catalog);
Transformer transformer = factory.newTransformer(xslSource);

Transformerオブジェクトを作成するためにファクトリで使用しているXSLソースに次のようなDTD、import文およびinclude文が含まれている場合、

<!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"/>

これらの参照を解決するために次のカタログ・エントリを使用できます。

<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"/>