4 XMLカタログAPI

XMLカタログAPIを使用してローカルXMLカタログを実装します。

Java SE 9では、新しいXMLカタログAPIが導入され、Organization for the Advancement of Structured Information Standards (OASIS) XMLカタログ、OASIS標準V1.1、2005年10月7日がサポートされるようになりました。 コア・ライブラリ・ガイドのこの章では、API、Java XMLプロセッサによるサポート、および使用パターンについて説明します。

XMLカタログAPIは、ローカル・カタログを実装するための単純なAPIであり、JDK XMLプロセッサによるサポートによってプロセッサや環境全体の構成が容易になり、その機能を活用することができます。

カタログ作成の詳細の学習

カタログ作成について学習するには、XMLカタログ、OASIS標準V1.1、2005年10月7日を参照してください。一部のLinuxディストリビューションの/etc/xml/catalogディレクトリの下にあるXMLカタログもまた、ローカル・カタログを作成するための参考になります。

XMLカタログAPIの目的

XMLカタログAPIとJava XMLプロセッサには、外部リソースを管理するための、開発者およびシステム管理者向けのオプションが用意されています。

XMLカタログAPIは、外部リソースが原因で発生する問題に対処するために設計された標準の、OASIS XMLカタログv1.1の実装を提供します。

外部リソースが原因で発生する問題

XML、XSDおよびXSLのドキュメントには、Java XMLプロセッサがドキュメントを処理するために取得する必要がある、外部リソースへの参照が含まれている可能性があります。外部リソースによってアプリケーションまたはシステムに問題が発生する場合があります。カタログAPIとJava XMLプロセッサには、これらの外部リソースを管理するための、開発者およびシステム管理者向けのオプションが用意されています。

外部リソースによって、アプリケーションまたはシステムの次の領域に問題が発生する場合があります:

  • 可用性: リソースがリモートの場合、XMLプロセッサはリソースをホストするリモート・サーバーに接続できる必要があります。接続性が問題となることはまれですが、アプリケーションの安定性に影響する要因になります。接続が多すぎると、リソースを保持しているサーバーに障害が発生し、アプリケーションに影響を及ぼす可能性があります。XMLカタログAPIを使用してこの問題を解決する例は、「XMLプロセッサでのカタログの使用」を参照してください。

  • パフォーマンス。接続性が問題になることはほとんどありませんが、リモート・フェッチによってアプリケーションのパフォーマンスに問題が生じることがあります。さらに、同じシステム上に同じリソースの解決を試行するアプリケーションが複数存在する場合があり、これによってシステム・リソースに無駄が生じます。

  • セキュリティ: リモート接続を許可すると、アプリケーションで信頼されないXMLソースが処理された場合にセキュリティ・リスクが発生します。

  • 管理性: システムで多数のXMLドキュメントを処理する場合、外部参照ドキュメントが(ローカルかリモートかに関係なく)保守上の問題になる可能性があります。

外部リソースが原因で発生する問題にXMLカタログAPIで対応する方法

アプリケーション開発者は、アプリケーションのすべての外部参照のローカル・カタログを作成し、カタログAPIを使用して参照をアプリケーション用に解決します。これによって、リモート接続が回避されるだけでなく、これらのリソースの管理が容易になります。

システム管理者は、システムのローカル・カタログを確立し、そのカタログを使用するようにJava VMを構成できます。次に、システム上のすべてのアプリケーションがアプリケーションのコードを変更することなく(Java SE 9と互換性があることを想定)、同じカタログを共有します。カタログを確立するために、一部のLinuxディストリビューションに含まれるカタログなどの既存のカタログを使用できます。

XMLカタログAPIのインタフェース

XMLカタログAPIにアクセスするは、XMLカタログAPIのインタフェースを使用します。

XMLカタログAPIのインタフェース

XMLカタログAPIでは、次のインタフェースが定義されています。

  • Catalogインタフェースは、XMLカタログ、OASIS標準V1.1 (2005年10月7日)で定義されているとおり、エンティティ・カタログを表します。Catalogオブジェクトは不変です。Catalogオブジェクトを作成したら、これを使用してsystempublic、またはuriエントリ内の一致を探します。カスタム・リゾルバを実装すると、カタログを使用してローカル・リソースを検索するのが便利であることがわかります。

  • CatalogFeaturesクラスには、javax.xml.catalog.filesjavax.xml.catalog.deferjavax.xml.catalog.prefer、およびjavax.xml.catalog.resolveなどの、カタログAPIがサポートする機能とプロパティが保持されています。

  • CatalogManagerクラスは、XMLカタログおよびカタログ・リゾルバの作成を管理します。

  • CatalogResolverインタフェースは、スキーマ検証で使用するSAX EntityResolver、StAX XMLResolver、DOM LS LSResourceResolver、および変換URIResolverを実装するカタログ・リゾルバです。インタフェースではカタログを使用して外部参照が解決されます。

CatalogFeaturesクラスの詳細

カタログ機能はCatalogFeaturesクラスにまとめて定義されています。機能はAPIレベルとシステム・レベルで定義されており、API、システム・プロパティおよびJAXPプロパティを使用して設定できます。APIを使用して機能を設定するには、CatalogFeaturesクラスを使用します。

次のコードでは、javax.xml.catalog.resolvecontinueに設定されるため、CatalogResolverによって一致が見つからなくても処理は続行します:

CatalogFeatures f = CatalogFeatures.builder().with(Feature.RESOLVE, "continue").build();

このcontinue機能をシステム全体に設定するには、JavaコマンドラインまたはSystem.setPropertyメソッドを使用します:

System.setProperty(Feature.RESOLVE.getPropertyName(), "continue");

このcontinue機能をJVMインスタンス全体に設定するには、jaxp.propertiesファイルに次の行を入力します:

javax.xml.catalog.resolve = "continue"

jaxp.propertiesファイルは通常、$JAVA_HOME/confディレクトリにあります。

resolveプロパティと、preferおよびdeferの各プロパティは、カタログの属性またはカタログ・ファイルのグループ・エンティティとして設定できます。たとえば、次のカタログでは、resolve属性が値continueで設定されています。属性は、次のようにgroupエントリでも設定できます。

<?xml version="1.0" encoding="UTF-8"?> 
<catalog
  xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"
  resolve="continue"
  xml:base="http://local/base/dtd/">
  <group resolve="continue">
    <system
      systemId="http://remote/dtd/alice/docAlice.dtd"
      uri="http://local/dtd/docAliceSys.dtd"/>     
  </group> 
</catalog>

より狭い範囲に設定されたプロパティは広い範囲に設定された属性をオーバーライドします。そのため、APIを使用して設定されたプロパティが常に優先されます。

XMLカタログAPIの使用

XMLカタログ標準の様々なエントリ・タイプを使用して、XMLソース・ドキュメントのDTD、エンティティおよび代替URI参照を解決します。

XMLカタログ標準では、数多くのエントリ・タイプが定義されています。そのうち、systemrewriteSystemおよびsystemSuffixの各エントリを含むシステム・エントリはXMLソース・ドキュメントのDTDおよびエンティティ参照を解決するために使用され、uriエントリは代替URI参照用です。

システム参照

CatalogResolverオブジェクトを使用してローカル・リソースを検索します。

ローカル・リソースの検索

次の例では、CatalogResolverオブジェクトを使用してローカル・リソースを検索する方法を示します。

次のXMLファイルを考えます:

<?xml version="1.0"?> 
<!DOCTYPE catalogtest PUBLIC "-//OPENJDK//XML CATALOG DTD//1.0" 
  "http://openjdk.java.net/xml/catalog/dtd/example.dtd">

<catalogtest>
  Test &example; entry
</catalogtest>

example.dtdファイルは、エンティティexampleを定義します:

<!ENTITY example "system">

ただし、XMLファイルにexample.dtdファイルへのURIが存在している必要はありません。一意の識別子を指定するのは、CatalogResolverオブジェクトでローカル・リソースを検索するのが目的です。これを行うには、catalog.xmlというカタログ・エントリ・ファイルにローカル・リソースを参照するためのsystemエントリを作成します。

<?xml version="1.0" encoding="UTF-8"?> 
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
  <system
    systemId="http://openjdk.java.net/xml/catalog/dtd/example.dtd"
    uri="example.dtd"/>
</catalog>

このカタログ・エントリ・ファイルとsystemエントリを使用して行うことは、デフォルトのCatalogFeaturesオブジェクトを取得し、カタログ・エントリ・ファイルへのURIを設定してCatalogResolverオブジェクトを作成するだけです:

CatalogResolver cr =
  CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogUri);

catalogUriは有効なURIである必要があります。次に例を示します。

URI.create("file:///users/auser/catalog/catalog.xml")

CatalogResolverオブジェクトをJDK XMLリゾルバとして使用できるようになりました。次の例では、SAX EntityResolverとして使用されています。

SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setEntityResolver(cr);

例ではシステム識別子に絶対URIが指定されていることに注意してください。これにより、リゾルバがカタログのsystemエントリに完全に一致するsystemIdを検索することが容易になります。

XMLのsystem識別子が相対である場合は、XMLプロセッサで指定のベースURIまたはソース・ファイルのURIを使用して絶対化する必要があるため、一致プロセスが複雑になります。その場合、システム・エントリのsystemIdが予期される絶対URIと一致する必要があります。より簡単に解決するには、次のようにsystemSuffixエントリを使用します。

<systemSuffix systemIdSuffix="example.dtd" uri="example.dtd"/>

systemSuffixエントリは、XMLソースのexample.dtdで終わる任意の参照と一致し、それをuri属性に指定されているとおりにローカルのexample.dtdファイルに解決します。systemIdが一意または正しい参照になるように、詳細を追加します。たとえば、systemIdSuffixxml/catalog/dtd/example.dtdに設定するか、XMLソース・ファイルとsystemSuffixエントリの両方でidが一意に一致するように名前を変更します(例: my_example.dtd)。

systemエントリのURIには、絶対URIまたは相対URIを指定できます。外部リソースの場所が固定されている場合は、絶対URIの方が一意性が保証されます。外部リソースがカタログ・エントリ・ファイルまたはアプリケーションに対して相対的な位置にある場合は、相対URIの方が効果的であり、アプリケーションのデプロイメントでインストール場所を意識する必要がありません。そのような相対URIは、ベースURIまたはカタログ・ファイルのURI (ベースURIが指定されていない場合)を使用して解決されます。前述の例では、example.dtdがカタログ・ファイルと同じディレクトリに置かれていることを想定しています。

パブリック参照

systemエントリのかわりにpublicエントリを使用して目的のリソースを検索します。

目的のリソースにsystemエントリが一致せず、PREFERプロパティがpublicと一致するように指定されている場合は、publicエントリを使用してsystemエントリと同じことを行えます。PREFERプロパティのデフォルト設定はpublicです。

パブリック・エントリの使用

解析済XMLファイルのDTD参照に"-//OPENJDK//XML CATALOG DTD//1.0"のようなパブリック識別子が含まれている場合は、カタログ・エントリ・ファイルのpublicエントリを次のように記述できます。

<public publicId="-//OPENJDK//XML CATALOG DTD//1.0" uri="example.dtd"/>

CatalogResolverオブジェクトを作成してこのエントリ・ファイルと使用する場合、example.dtdpublicIdプロパティを使用して解決されます。CatalogResolverオブジェクトの作成例は、「システム参照」を参照してください。

URI参照

uriエントリを使用して目的のリソースを検索します。

urirewriteURIおよびuriSuffixなどのURIタイプのエントリは、システム・タイプのエントリと同じように使用できます。

URIエントリの使用

XMLカタログ標準では、systemタイプのエントリにはDTD参照の解決、uriタイプのエントリにはその他すべてのプリファレンスが指定されていますが、Java XMLカタログAPIではそのような区別がありません。これは、XMLResolverおよびLSResourceResolverなどの既存のJava XMLリゾルバの仕様ではプリファレンスを指定しないためです。urirewriteURIおよびuriSuffixなどのuriタイプのエントリは、systemタイプのエントリと同じように使用できます。uri要素は、代替URI参照とURI参照を関連付けるために定義されます。system参照の場合、これはsystemIdプロパティです。

そのため、systemエントリは一般的にはDTD参照に使用されますが、次の例のようにsystemエントリをuriエントリに置き換えることができます。

<system
  systemId="http://openjdk.java.net/xml/catalog/dtd/example.dtd"
  uri="example.dtd"/>

uriエントリの例を次に示します。

<uri name="http://openjdk.java.net/xml/catalog/dtd/example.dtd" uri="example.dtd"/>

systemエントリがDTDのために使用されるのに対して、uriエントリはXSDおよびXSLのインポートとインクルードなどのURI参照に使用されます。次の例では、XSLインポートの解決にuriエントリが使用されています。

XMLカタログAPIのインタフェースで説明しているように、XMLカタログAPIでは、EntityResolverXMLResolverURIResolverLSResolverなどのJava XMLリゾルバを拡張するCatalogResolverインタフェースが定義されています。そのため、CatalogResolverオブジェクトは、SAX、DOM、StAX、スキーマ検証およびXSLT変換で使用できます。次のコードでは、CatalogResolverオブジェクトがデフォルトの機能設定で作成されます。

CatalogResolver cr =
  CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogUri);

コードでは次に、このCatalogResolverオブジェクトをURIResolverオブジェクトが予期されるTransformerFactoryクラスに登録します。

TransformerFactory factory = TransformerFactory.newInstance();
factory.setURIResolver(cr);

かわりに、コードでCatalogResolverオブジェクトをTransformerオブジェクトに登録することもできます。

Transformer transformer = factory.newTransformer(xslSource); 
transformer.setURIResolver(cur);

XSLソース・ファイルに、xslImport.xslファイルをXSLソースにインポートするためのimport要素が含まれているとします。

<xsl:import href="pathto/xslImport.xsl"/>

import参照をインポート・ファイルが実際にある場所に解決するには、Transformerオブジェクトを作成する前にCatalogResolverオブジェクトがTransformerFactoryクラスに設定されており、カタログ・エントリ・ファイルに次のようなuriエントリが追加されている必要があります。

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

システム参照における絶対URIと相対URI、およびsystemSuffixエントリまたはuriSuffixエントリの使用に関する検討は、uriエントリにも当てはまります。

Java XMLプロセッサ・サポート

XMLカタログ機能を標準Java XMLプロセッサと使用します。

XMLカタログ機能は、SAXおよびDOM (javax.xml.parsers)、StAXパーサー(javax.xml.stream)、スキーマ検証(javax.xml.validation)、XML変換(javax.xml.transform)などのJava XMLプロセッサを使用してサポートされます。

これは、XMLプロセッサの外部にCatalogResolverオブジェクトを作成する必要がないことを意味します。カタログ・ファイルは、Java XMLプロセッサに直接登録するか、システム・プロパティを使用して指定するか、jaxp.propertiesファイルに指定できます。XMLプロセッサによって自動的にカタログを使用したマッピングが実行されます。

カタログ・サポートの有効化

プロセッサでのXMLカタログ機能のサポートを有効化するには、USE_CATALOG機能がtrueに設定されており、少なくとも1つのカタログ・エントリ・ファイルが指定されている必要があります。

USE_CATALOG

Java XMLプロセッサによって、XMLカタログ機能がUSE_CATALOG機能の値に基づいてサポートされるかどうかが決定されます。デフォルトでは、USE_CATALOGはすべてのJDK XMLプロセッサに対してtrueに設定されています。Java XMLはさらにカタログ・ファイルの使用可能性を確認し、USE_CATALOG機能がtrueでカタログが使用可能である場合にのみ、XMLカタログAPIの使用を試行します。

USE_CATALOG機能は、XMLカタログAPI、システム・プロパティおよびjaxp.propertiesファイルによってサポートされます。たとえば、USE_CATALOGtrueに設定されており、特定のプロセッサに対するカタログ・サポートを無効化する場合は、プロセッサのsetFeatureメソッドを使用してUSE_CATALOG機能をfalseに設定します。次のコードでは、XMLReaderオブジェクトに対して、USE_CATALOG機能が指定値のuseCatalogに設定されます。

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
XMLReader reader = spf.newSAXParser().getXMLReader();
if (setUseCatalog) {
   reader.setFeature(XMLConstants.USE_CATALOG, useCatalog); 
}

一方、環境全体でカタログをオフにする必要がある場合は、jaxp.propertiesファイルに次の行を構成します。

 javax.xml.useCatalog = false;

javax.xml.catalog.files

javax.xml.catalog.filesプロパティはXMLカタログAPIによって定義され、JDK XMLプロセッサにその他のカタログ機能とともにサポートされます。システム・プロパティまたはjaxp.propertiesファイルを使用してプロセッサにFILESプロパティを設定するだけで、解析、検証または変換プロセスでカタログ機能を使用できます。

カタログURI

カタログ・ファイル参照は、file:///users/auser/catalog/catalog.xmlのような有効なURIである必要があります。

システムまたはカタログ・ファイルのURIエントリのURI参照は、絶対または相対で指定できます。相対の場合は、カタログ・ファイルのURIまたはベースURI(指定された場合)を使用して解決されます。

システム・エントリまたはuriエントリの使用

XMLカタログAPIを直接使用する場合(例はXMLカタログAPIのインタフェースを参照)、JDK XMLプロセッサでCatalogFeaturesクラスのネイティブ・サポートを使用すると、systemエントリとuriエントリの両方が機能します。通常は、最初にsystemエントリ、次にpublicエントリが検索され、一致が見つからない場合はプロセッサによって引き続きuriエントリが検索されます。systemエントリとuriエントリの両方がサポートされるため、systemまたはuriのどちらのエントリを使用するかを選択する場合は、XML仕様の慣例に従うことをお薦めします。たとえば、DTDはsystemIdを使用して定義されるため、systemエントリを使用することをお薦めします。

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

リゾルバのコール順序

JDK XMLプロセッサはカタログ・リゾルバの前にカスタム・リゾルバをコールします。

カタログ・リゾルバより優先されるカスタム・リゾルバ

カタログ・ファイルが設定されているJDK XMLプロセッサでは、カタログ・リゾルバ(CatalogResolverインタフェースで定義される)を使用して外部参照を解決できます。ただし、カスタム・リゾルバも指定されている場合は、これが常にカタログ・リゾルバより優先されます。つまり、JDK XMLは最初にカスタム・リゾルバをコールして外部リソースの解決を試行します。正常に解決された場合、プロセッサはカタログ・リゾルバをスキップして続行します。カスタム・リゾルバがないか、カスタム・リゾルバによる解決でnullが返された場合にのみ、プロセッサはカタログ・リゾルバをコールします。

カスタム・リゾルバを使用するアプリケーションでは、カスタム・リゾルバが処理できないリソースを解決するために、追加のカタログを設定します。コードを変更できない既存のアプリケーションでは、システム・プロパティを使用してカタログを設定するか、jaxp.propertiesファイルで外部参照を(この設定によってカスタム・リゾルバが処理する既存のプロセスに干渉しないことがわかっている)ローカル・リソースにリダイレクトします。

エラーの検出

問題を分離して構成の問題を検出します。

XMLカタログ標準では、プロセッサがリソースの障害からリカバリできることを必要としています。そのため、XMLカタログAPIでは、問題のあるカタログ・エントリ・ファイルはエラーが発行されることなく無視されます。これによって構成の問題を検出するのが難しくなります。

構成の問題の検出

構成の問題を検出するには、カタログを1つずつ設定し、RESOLVEの値をstrictに設定し、一致が見つからなかった場合はCatalogException例外を確認することで、問題を分離します。

表4-1 RESOLVEの設定

RESOLVEの値 CatalogResolverの動作 説明

strict(デフォルト)

指定された参照に一致が見つからなかった場合はCatalogExceptionがスローされます

参照の不一致は、カタログの内容またはカタログの設定にエラーがあることを示します。

continue

動作なし

これは、カタログに含まれていない外部参照を解決するためにXMLプロセッサを続行する、本番環境での使用に適しています。

ignore

動作なし

外部参照のスキップが許可されるSAXのようなプロセッサの場合、ignore値はCatalogResolverオブジェクトに、空のInputSourceオブジェクトを返すことを指示します。これによって外部参照はスキップされます。