オープン パッケージ規則のアドレス指定モデル

 

David Meltzer と Andrey Shur
Microsoft Corporation

2006 年 6 月

適用対象:
   Open Packaging Conventions
   Microsoft Office 2007
   Microsoft Windows Vista
   [Microsoft .NET Framework]

概要:この記事では、パッケージとそのパーツの対処方法、パッケージ パーツ内の相対参照の解決方法、アプリケーションがパッケージ アドレッシング モデルを.NET Frameworkとクラスの助けを借りて利用する方法など、Open Packaging Conventions で使用されるアドレス指定モデルの概要について説明します。 (16ページ印刷)

内容

はじめに
アドレス指定モデル
"pack:" URI のプログラミング サポート
リファレンス

はじめに

Office 2007 と Windows Vista の設計の一環として、Microsoft は Open Packaging Conventions を導入しました。 これらの規則では、コンテンツを "パッケージ" で整理する方法について説明します。コンテンツの例としては、ドキュメント、メディアのコレクション、アプリケーション ライブラリなどがあります。 パッケージは、コンテンツのすべてのコンポーネントを 1 つのオブジェクトに集約します。

ワープロ アプリケーションでは、たとえば、パッケージを使用して、ドキュメントのページ、必要なフォント、ページ上の画像、グラフ、注釈を格納できます。 ドキュメントの表示または管理アプリケーションでは、パッケージ内のコンテンツの一部のみを表示できます。 アプリケーションでは、XML Paper Specification (XPS) などのパッケージベースの形式を使用して、固定レイアウトのコンテンツとリソースをプリンターに送信できます。

この記事では、パッケージとそのパーツの対処方法、パッケージ パーツ内の相対参照の解決方法など、Open Packaging Conventions で使用されるアドレス指定モデルの概要について説明します。 この記事では、.NET Frameworkと .NET Framework 3.0 クラスを使用して、アプリケーションでパッケージ アドレス指定モデルを利用する方法についても説明します。 この記事は、主にパッケージを処理、生成、または使用するアプリケーションの開発者向けに作成されています。

パッケージ アドレス指定モデルを実装するために必要な完全な規範情報については、Open Packaging Conventions の仕様を参照してください。 .NET Framework 3.0 および .NET SDK では、説明されているクラスとメソッドに関する詳細情報が提供されます。

この概要に記載されている資料は、URI 仕様に関する基本的な知識を前提としています。 RFC 3986 に従って、 URIURI 参照スキーム コンポーネント機関コンポーネントパス コンポーネントパス絶対参照、 相対参照という用語が使用されます。 URI という用語は、常に URI の絶対形式を表します。スキーム コンポーネントが存在し、他のすべてのコンポーネントがスキーム固有の文法と一致します。 ここで使用する アドレス指定可能という用語は、リソースを識別する URI が存在することを示します。

アドレス指定モデル

Open Packaging Conventions では、パッケージのコンテンツとリソースを整理するための論理モデルを定義し、ZIP、XML、およびその他の公開されているテクノロジに基づいて、この論理モデルから物理的な表現へのマッピングを提供します。

Open Packaging Conventions で説明されている論理 パッケージ モデル は、パーツのコレクションを保持するパッケージ抽象化を定義します。 パーツは相互にリレーションシップを持ち、パッケージはパーツとのリレーションシップを持つことができます。 パッケージ モデルでは、パッケージ内のパーツの名前付け、参照、および関連方法を指定します。 規約によって定義された アドレス指定モデル は、パッケージ内のパーツ リソースを参照および取得するための基礎です。

アドレス指定可能なパッケージ リソース

パッケージ インスタンス全体は、 パッケージ インスタンス に保持されている各部分と同様に、アドレス指定可能なリソースです。

パッケージをユニットとしてアドレス指定する

アプリケーションでは、任意のスキーム ("http:"、"ftp:"など) で URI を使用してパッケージを単位としてアドレス指定し、パッケージ全体を構成するビットのストリームを取得できます。

アプリケーションでは、Open Packaging Conventions によって定義された "pack:" URI スキームを使用してパッケージに対処することもできます。 このスキームでは、パッケージを識別する完全な URI が、エンコードされた形式の "pack:" URI の機関コンポーネントに保持されることを指定します。

例: パッケージのアドレス指定

パッケージ リソースは、次の例の "http:" URI と "pack:" URI (それぞれ) によってアドレス指定されます。

http://www.site.com/windows/p1.xps

pack://http%3a,,www.site.com,windows,p1.xps/

取得したパッケージ リソースの MIME の種類は、パッケージのファイル形式を示します。たとえば、XPS ドキュメント形式 (.xps)、Office Open XML 形式 (.docx)、または Open Packaging Conventions に準拠するその他の形式を指定できます。

さまざまな理由 (パフォーマンスの向上など) のために、アプリケーションでは、"pack:" URI の機関コンポーネントとして、ドメインに固有の URI を使用できます。 このような URI は、特定のアプリケーションのコンテキストでのみ解決できます。 このようなアプリケーション固有の URI に使用されるプログラミング手法については、後述の「The PackageStore」を参照してください。

パッケージ内のパーツのアドレス指定

パッケージ内のパーツは、"pack:" URI を使用してアドレス指定されます。 パーツをアドレス指定する "pack:" URI の構造は、pack://< authority><パスです。>

例: 部分のアドレス指定

pack://http%3a,,www.site.com,windows,p1.xps/fonts/arial.ttf は、 によってhttp://www.site.com/windows/p1.xpsアドレス指定されたパッケージ内の /fonts/arial.ttf という名前の部分に対応します。

機関コンポーネントは、パッケージ全体のエンコードされた URI を保持します。パス コンポーネントは、そのパッケージ内のパーツの名前を保持します。 パーツ名は、パス絶対 URI コンポーネント ([2]、セクション 3.3) に定義されている文法に準拠し、いくつかの追加の制限 ([1]、セクション 2.1.1.1) を使用します。

例: パーツ名

/documents/doc1.xaml

/pages/page4.xaml

/fonts/arial.ttf

パーツ名は、大文字と小文字を区別しない ASCII 文字列です。 パッケージ内のすべてのパーツには一意の名前があります。

フラグメント識別子を使用してパーツを参照する

Open Packaging Conventions を使用する一部のアプリケーションでは、形式固有のフラグメント識別子を持つパッケージ ユニットの "pack:" 以外の URI を使用してパーツを参照できます。

例: "pack:" 以外の URI を使用してパーツを参照する

URI http://www.site.com/windows/p1.xps\#15 は、p1.xps ドキュメントのページ 15 を表すパーツを参照するために使用されます ([3]、セクション 9.2.2 および 9.2.3)。

これは有効であり、特定のシナリオでは、"pack:" 以外の URI でパーツを参照すると便利ですが、そのような URI を基本 URI として使用して、パーツ コンテンツ内の相対参照を解決することはできません。

パーツ内のエントリの参照

パーツは、パッケージ内で最も詳細なアドレス指定可能なリソースです。 ただし、アプリケーションでは、パーツのコンテンツ内のエントリを参照する必要がある場合があります。 特定のコンテンツ タイプの場合、エントリはフラグメント識別子 ([2]、セクション 3.5) を使用して参照できます。 Open Packaging Conventions では、フラグメント識別子は指定されません。 フラグメント識別子を使用するアプリケーションは、それらを適切に処理します。

例: パーツ内のエントリを参照する

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml#//[@Id="A012"] は、/pages/page1.xaml という名前のパーツのコンテンツ内の XML ノードのセットを参照し、Id 属性値が A012 です。

入れ子になったパッケージ

パッケージは入れ子にすることができます。 パッケージ内のパーツは、パッケージ全体を含め、任意の種類のコンテンツを保持できます。 入れ子になったパッケージの部分は、この入れ子になったパッケージを保持している部分を示す機関コンポーネント ([1]、付録 D.3) を使用して、"pack:" URI で対処できます。

例: 入れ子になったパッケージ内のパーツのアドレス指定

にあるパッケージにはhttp://www.site.com/package、/nested-package という名前のパーツが含まれています

,

"pack:" URI pack://http%3a,,www.site.com,package/nested-package によってアドレス指定されます。

上記の URI でアドレス指定されたパーツには、パッケージ ユニットが含まれています。パッケージ ユニットには 、/p1.xaml という名前のパーツが含まれています。

入れ子になったパッケージ内のこの部分のアドレスは次のとおりです。

pack://pack%3a,,http:%253a%2c%2cwww.site.com%2cpackage,nested-package/p1.xaml

パーツ コンテンツ内の参照

XML などの特定の種類のコンテンツを持つパーツには、URI 参照を含めることができます。 URI 参照には、URI または相対参照を指定できます。 URI 参照は、コンテンツ内で Unicode 文字列で表すことができます。 このような URI 参照を解決するアプリケーションでは、文字列を URI 形式に変換する必要があります ([4]、セクション 3.1)。

相対参照は、参照を含むコンテンツのベース URI を基準にして表される URI です。 パーツ コンテンツの既定のベース URI は、パーツをアドレス指定する "pack:" URI です。

例: ベース URI

でアドレス指定されたhttp://www.site.com/windows/p1.xpsパッケージ内の /pages/page1.xaml という名前のパーツのベース URI は次のとおりです。

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml

パーツ コンテンツのエントリ内の相対参照を解決するために代替ベース URI が必要な場合は、アプリケーションで代替を明示的に指定する必要があります。 特定のコンテンツ タイプは、代替ベース URI を指定する特定の方法を公開します。 たとえば、XML では xml:base 属性が使用され、HTML では基本>要素が<使用され、Open Packaging Conventions では Relationship 要素に TargetMode 属性が使用されます。

相対参照のベース URI としてパーツの "pack:" URI を使用すると、相対参照がまれに使用されるネットワーク パス形式 (つまり、"//" で始まる相対参照) に含まれていない限り、参照先のリソースが同じパッケージ ([2]、セクション 5.2) 内のパーツであることが保証されます。

例: 相対参照の解決

相対参照 ../..pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml として扱われるパーツ内の /page2.xaml は、/page2.xaml という名前のパーツをアドレス指定して pack://http%3a,www.site.com,windows,p1.xps/page2.xaml に解決されます。

パッケージ プロデューサーは、パーツ名を有効な相対参照形式として使用できます。 ただし、パーツ名を相対参照として使用する場合、プロデューサーは、参照されるパーツをパッケージの外部で抽出されたリソースとしても対処できるかどうかを検討する必要があります。 パッケージからパーツを抽出すると、相対参照として使用されるパーツ名が想定どおりに解決されないことがあります。 パーツ名の文法で指定されたパーツ名の先頭のスラッシュは、このような相対参照が現在の機関のルートから解決されることを意味します。

例: 抽出されたリソースのアドレス指定

/doc1/pages/page1.xaml という名前のパーツのコンテンツでは、相対参照 /page2.xaml は /page2.xaml という名前のパーツを指し、相対参照 ./page3.xaml/doc1/pages/page3.xaml という名前のパーツを指します。

パーツ /doc1/pages/page1.xaml/doc1/pages/page3.xaml、および /part2.xaml がパッケージから file:///c:/mydocs/doc1/pages/page1.xamlfile:///c:/mydocs/doc1/pages/page3.xamlおよび file:///c:/mydocs/page2.xaml という名前のファイルに抽出された後、相対参照 ./page3.xaml はファイル file:///c:/mydocs/doc1/pages/page3.xaml に対応します。ただし、相対参照 /page2.xaml、file:///page2.xaml という名前のファイルに対応するようになりました。

リレーションシップ内の相対参照

オープン パッケージ規則では、パッケージ内のソース パーツとターゲット パーツ間の 接続をリレーションシップ として定義します ([1]、セクション 1.3)。

リレーションシップは、ソースに基づいてグループ化され、格納されます。 リレーションシップ パーツは、同じソース パーツから生成されたリレーションシップを保持します。 各リレーションシップは、このリレーションシップ パーツのコンテンツ内の XML 要素によって記述されます。 リレーションシップ パーツは、リレーションシップ パーツに対して定義された名前付け規則を使用して、このソース パーツに一意に関連付けられます (その逆も同様)。

各 Relationship 要素で指定された URI の既定のベース URI は、ソース部分の "pack:" URI です ([1]、セクション 1.3.5)。 Relationship 要素の TargetMode 属性は、指定されたリレーションシップのベース URI を示します。

例: Relationship 要素

/pages/page1.xaml という名前のソース パーツから同じパッケージ内のターゲット パーツ /fonts/arial.ttf へのリレーションシップを定義するリレーションシップ パーツ内の要素は、次のようになります。

<リレーションシップの種類="https://schemas.microsoft.com/xps/2005/06/restricted-font"

TargetMode="Internal" Id="A123" Target="../fonts/arial.ttf"/>

TargetMode 属性の内部値は、Relationship 要素のベース URI がリレーションシップ パーツのコンテンツの既定値であり、リレーションシップ ソース パーツの "pack:" URI と同じであることを示します。 前の例では、 Relationship 要素のベース URI は /pages/page1.xaml パーツの "pack:" URI です。

リレーションシップは、パッケージ全体の場所に対する外部リソースをターゲットにすることもできます。

例: 外部ターゲットとの関係

file:///c:/office12/sample.docxにあるパッケージの場合、 XML 要素

<リレーションシップ Id="rId9"

Type="https://schemas.microsoft.com/office/2006/relationships/image"

Target="Icon.JPG" TargetMode="External"/>

は、 ファイルを対象とするリレーションシップ file:///c:/office12/icon.jpg定義します。

TargetMode 属性の External 値は、リレーションシップがパッケージの外部にあるリソースをターゲットにする必要があることを指定します。 Target 属性が相対参照を保持している場合は、ベース URI が必要です。 このリレーションシップ要素のベース URI は、パッケージ全体の URI である必要があります。

リレーションシップへの参照の委任

パッケージベースの形式によっては、コンテンツで URI 参照を使用し、リレーションシップへの参照を委任することを避ける場合があります。 この委任手法は、各 Relationship 要素で一意の ID 値を使用して、パーツ コンテンツ内の相対参照を対応するリレーションシップにマップすることに基づいています。

例: パーツ コンテンツ内の相対参照をリレーションシップにマッピングする

file:///c:/office12/sample.docx にあるパッケージには、/word/document.xml という名前のパーツがあります。

<a:blip relEmbed="rId6" relLink="" w="0" h="0"/>.

このパーツにアタッチされているリレーションシップ パーツは、 要素を保持します。

<リレーションシップ Id="rId6"

Type="https://schemas.microsoft.com/office/2006/relationships/image"

TargetMode="Internal" Target="media/image1.jpeg"/>.

これにより、 要素が /word/media/image1.jpeg という名前の部分にリンクされます。

このアプローチの利点は、アプリケーションがパーツ内のコンテンツを見ることなく、パッケージ内のすべての参照を識別して維持できることです。

ただし、参照がリレーションシップに委任されている場合、緩いファイルに抽出されたパッケージ パーツが正しく機能しない可能性があります。 リレーションシップ ターゲットを抽出後に機能させるには、使用するアプリケーションでは、リレーションシップに関する特別な知識、リレーションシップ パーツの名前付けのための Open Packaging Conventions、およびリレーションシップ ファイルの基本 URI の定義が必要です。

"pack:" URI のプログラミング サポート

パッケージを生成または使用するアプリケーションは、パッケージとパーツ のアドレスで動作し、パーツのコンテンツ内の相対参照を解決します。 .NET Framework 3.0 には、Microsoft によって提供される次世代マネージド API のセットが提供され、Open Packaging Conventions のアドレス指定モデルをサポートするクラスが含まれています。 これらのクラスを使用すると、アプリケーションは参照を作成および解析し、パッケージ リソースを取得できます。 PackUriHelper クラスは、"pack:" URI の処理を容易にするために使用されます。 PackWebRequest クラスは、"pack:" URI を使用してアドレス指定されたリソースを取得するために使用されます。

このセクションでは、これらのサービスが参照の作成、解析、および解決で実行する関数について説明します。

パッケージ サービスを使用できるようにする

パッケージ 化サービス クラスを使用するには、.NET Framework バージョン 3.0 (またはそれ以上) をインストールする必要があります。 クラスは System.IO.Packaging 名前空間にあります。

"pack:" URI が関係する操作に System.Uri を使用する前に、アプリケーション ドメインに "pack:" URI スキームを登録する必要があります。 "pack:" URI スキームを登録する最も簡単な方法は、 PackUriHelper クラスの任意のメソッドを呼び出すことです。 次の例に示すように、 UriParser.Register メソッドを使用して、ヘルパー クラスを呼び出さずにスキームを登録することもできます。 ただし、この方法を使用するには、セキュリティアクセス許可が必要です。

例: "pack:" URI スキームの登録

//To register the "pack:" URI scheme without calling PackUriHelper

UriParser.Register(new GenericUriParser
   (GenericUriParserOptions.GenericAuthority),
      "pack", -1);

ターゲット リソースの "pack:" URI の取得

パッケージを使用する場合、パッケージ全体または一度に 1 つのパーツをオブジェクトとして取得できます。 どちらの場合も、 PackUriHelper.Create メソッドを使用して、パッケージまたはパーツ リソースの "pack:" URI を作成できます。 この "pack:" URI は、リソースを取得するために PackWebRequest メソッドに渡されます。 PackWebRequest については、次のセクション「PackWebRequest を使用したパッケージ リソースの取得」で詳しく説明します。

PackUriHelper クラスと PackWebRequest クラスを使用してパッケージの使用をサポートする方法の一般的な例を、次の手順で詳しく説明します。 パッケージ URI とパーツ URI がわかっている場合、アプリケーションでは次のことができます。

  1. PackUriHelper を使用して、パッケージ URI とパーツ URI から "pack:" URI を作成します。
  2. PackWebRequest を呼び出して、ビットのストリームを取得します。
  3. パーツの内容を読み込み、解析して相対参照を取得します。
  4. パーツベース URI (手順 1 で構成された "pack:" URI) に対するこれらの相対参照を解決します。
  5. System.Uri を使用して相対参照を解決し、PackWebRequest を使用して指定されたリソースを取得します。

目的のパッケージの "pack:" URI の作成

パッケージの "pack:" URI は、 PackUriHelper.Create メソッドを使用して作成できます。

例: PackUriHelper.Create

//Given the URI for a package
Uri packageUri = new Uri("http://www.newsdocs.com
               /local/today.container");

//Use the Create method to create a "pack:" URI from a non-"pack:" URI
Uri packUri = PackUriHelper.Create(packageUri);

//The resulting packUri value is
//"pack://http%3a,,www.newsdocs.com,local,today.container/"

作成された "pack:" URI は、パッケージ リソースを取得するために PackWebRequest に渡されます。

必要なパーツの "pack:" URI の作成

パーツの "pack:" URI は、 PackUriHelper.Create メソッドを使用して作成できます。

例: PackUriHelper.Create

//Given the URI for package 
Uri packageUri = new Uri("http://www.newsdocs.com
               /local/today.container");

//Given the URI for a part
Uri partUri = new Uri("/sports.xml", UriKind.Relative);

//Use the PackUriHelper.Create method to create a "pack:" URI

Uri packUri = PackUriHelper.Create (packageUri, partUri);

//The resulting packUri value is
//"pack://http%3a,,www.newsdocs.com,local,today.container/sports.xml"

作成された "pack:" URI は、パーツ リソースを取得するために PackWebRequest に渡されます。

相対参照の解決

パーツのコンテンツを処理するときに、他のパーツまたはリソースを参照する相対参照が見つかる場合があります。 これらの参照を解決することは、参照先のリソースを取得する最初の手順です。

パーツのコンテンツ内の相対参照は、パーツのベース URI に対して、ターゲット パーツの "pack:" URI に対して解決されます。 パッケージからパーツ リソースを取得するために、ターゲット パーツの "pack:" URI が PackWebRequest に渡されます。 ターゲット パーツの "pack:" URI から派生したターゲット パーツの名前を使用して、 Package.GetPart メソッドにパーツ名を渡すことで、ターゲット パーツを取得することもできます。

ターゲット パーツへの相対参照を解決する場合、最初に使用できる情報と、パッケージが開いている (または開くことができる) かどうかに応じて、解決に使用できるパスがいくつかあります。 これらのパスの 2 つを次に示します。

  • 開始時:

    1. 参照を含むパーツの "pack:" URI は既知です。
    2. パッケージが開いていません。
    //Given the "pack:" URI for the part "/files/fixeddoc.xaml"
    //packUri =
    // "pack://http%3a,,www.newsdocs.com,local,today.container
    // /files/fixeddoc.xaml"
    
    //The part "/files/fixeddoc.xaml" contains 
    //the relative reference "../images/1.jpg"
    
    Uri relativeReference = new Uri("../images/1.jpg", 
                      UriKind.Relative);
    
    //Use System.Uri to directly obtain the absolute target URI
    
    Uri targetPackUri = new Uri(packUri, relativeReference);
    
    //The value of the resulting targetPackUri is 
    //"pack://http%3a,,www.newsdocs.com,local,today.container
    // /images/1.jpg"
    
    //Now another PackWebRequest can be made using 
    //this targetPackUri value.
    
  • 開始時:

    1. 参照を含むパーツの名前は既知です。
    2. パッケージが開いています。
    //Given "package" as the current instance of the Package class.
    //Given the relative reference = "../../images/1.jpg"
    
    Uri relativeReference = new Uri("../../images/1.jpg", 
                      UriKind.Relative);
    
    //Given the URI of the part that contains the relative reference
    
    Uri partUri = new Uri("/files/fixeddoc.xaml");
    
    //Use PackUriHelper.ResolvePartUri to obtain the resolved part URI 
    //of the target based on the part URI above and the relative 
    //reference in that part
    
    Uri targetPartUri = PackUriHelper.ResolvePartUri
                   (partUri, relativeReference);
    
    //The resulting targetPartUri value is "fixeddoc.xaml"
    //Now use the package.GetPart method to obtain the target part
    
    PackagePart packagePart = package.GetPart(targetPartUri);
    

パッケージ クラスへのパーツ名の指定

パッケージを開くと、 Package クラスはパッケージにパーツを追加したり、パーツを取得したり、パーツを削除したりするのに役立ちます。 Package.AddPart、Package.DeletePartPackage.GetPart などの Package クラスのメソッドは、パラメーターとして一部の URI を受け取ります。 PackUriHelper.CreatePartUri メソッドを使用すると、パッケージのベース URI を基準とする参照から有効なパーツ名を作成できます。

例: PackUriHelper.CreatePartUri

//Given a URI

Uri partUri = PackUriHelper.CreatePartUri 
            (new Uri "files/a.xaml",UriKind.Relative))

//The URI will be checked for validity, and a leading slash
//will be added. The resulting partUri value is "/files/a.xaml"

相対参照を生成するためのサービス

オーサリング アプリケーションでは、ソース パーツのコンテンツに配置されたときにターゲット パーツを指す相対参照を派生させる必要がある場合があります。 GetRelativeUri メソッドは、この目的を果たします。

例: GetRelativeUri の例

//Given the URI of the source part

Uri sourcePartUri = new Uri("/tiles/pages/a.xaml", UriKind.Relative);

//Given the URI of the target part

Uri targetPartUri = new Uri("/images/event1/1.jpg", UriKind.Relative);

//Use PackUriHelper.GetRelativeUri to generate the relative reference
//that will be placed in the content of the source part.

Uri relativeReference = PackUriHelper.GetRelativeUri
               (sourcePartUri, targetPartUri);

//The resulting relativeReference value is "../../images/event1/1.jpg"

PackWebRequest を使用したパッケージ リソースの取得

アプリケーションは、System.Net.WebRequest から派生したクラス PackWebRequest を使用してパッケージとパーツ リソースを取得できます。 PackWebRequest は、指定された "pack:" URI によってアドレス指定されたリソースを返します。

一般に、"pack:" URI の PackWebRequest を開始する手順は次のとおりです。

  1. "pack:" URI 文法がチェックされます。
  2. 機関コンポーネントは "pack:" URI から抽出され、絶対 URI の文法に従うかどうかを確認します。
  3. "pack:" URI のパス コンポーネントが空の場合:
  • 機関コンポーネントのパッケージ ストリームが取得され、呼び出し元に返されます。

    それ以外の場合、パス コンポーネントが空でない場合:

    1. オープン パッケージは、機関コンポーネントによって識別されるリソースに対して取得されます。 CachePolicy セットに応じて、PackWebRequestPackageStore から開いているパッケージを取得するか、パッケージ リソースの内部 WebRequest を作成し、返されたパッケージ ストリームからパッケージを開きます。
    2. パーツは、パーツ名として "pack:" URI のパス コンポーネントを使用して取得されます。
    3. パーツ ストリームが取得され、呼び出し元に返されます。

PackWebResponse.GetStream は、パッケージ全体 (パッケージ ストリーム) またはパッケージ内の 1 つのパーツ (パーツ ストリーム) を表すビット のストリームを返します。

ほとんどの WebResponse ストリームとは異なり、パッケージ ストリームは Stream.Seek を使用してシーク可能です。 パッケージ ストリームを使用して、パッケージ オブジェクトを作成できます。

"http:" プロトコルを介してパッケージ リソースを操作する場合、 PackWebRequest では、パーツの 段階的な読み込みが サポートされます。つまり、パーツ データまでパッケージ内のすべてのデータを読み込まずに、任意の順序でパーツ リソースを取得できます。

PackWebRequest には、リソースを消費するための機能のみが用意されています。 サーバーへのデータの送信や送信には使用できません。

PackWebRequest は現在、非同期操作 ( BeginGetResponse など) をサポートしていません。 また、PackWebRequest は入れ子になったパッケージをサポートしていません (前述の「パッケージ内のパーツのアドレス指定」を参照)。

The PackageStore

他のパーツへの参照が多数含まれるパーツを含むパッケージを読み込む場合は、 PackageStore を使用してリソース要求の応答時間を短縮し、ネットワーク トラフィックを削減できます。 PackageStore は、開いているパッケージへの参照のアプリケーション ローカル ディクショナリです。 PackageStore に登録されている各パッケージは、キー URI 値によって識別されます。

PackageStore を使用すると、PackWebRequest は、そのパッケージから別のリソースが必要になるたびにサーバー要求を行うことなく、パッケージから必要に応じてリソースを取得できます。

PackageStorePackWebRequest の呼び出しの結果として自動的に変更されません。明示的に変更する必要があります。 PackageStore で開くパッケージへの参照を追加または削除するには、Package.AddPackage と Package.RemovePackage の 2 つのパブリック メソッドが使用されます

PackWebRequest に設定されている既定のキャッシュ ポリシー (CacheIfAvailable) により、クラスは PackageStore を使用してパッケージを取得しようとします。 PackWebRequest は、次のセクション「キャッシュ ポリシー」で説明するようにキャッシュ ポリシーを BypassCache に設定することで、リソースを取得するときに PackageStore の内容を無視するように強制できます。

既定のキャッシュ ポリシーに従ってパッケージまたはパーツのビットを取得する場合、 PackWebRequest はまず PackageStore をチェックして、"pack:" URI の機関コンポーネントと等しいキーに登録されているパッケージがあるかどうかを確認します。 PackageStore にキーのパッケージが含まれていない場合、PackWebRequest は内部 WebRequest を作成し、"pack:" URI の機関コンポーネントを使用してリソースをダウンロードします。

キャッシュ ポリシー

キャッシュ ポリシーは、 リソースのキャッシュされたコピーを使用してリソース要求を入力できるかどうかを判断するために使用されるルールを定義します。

PackWebRequest を使用する場合、明示的に設定できる 2 つのレベルのキャッシュ ポリシーがあります。 PackWebRequest 自体にキャッシュ ポリシーを設定し、PackageStore との対話を制御できます。 また、内部 WebRequest によって制御されるキャッシュに対してキャッシュ ポリシーを設定することもできます。 内部 WebRequest には、PackWebRequest.GetInternalRequest() を使用して PackWebRequest からアクセスできます。

PackWebRequest.CachePolicyCacheOnly に設定されている場合、内部 WebRequest に設定されたキャッシュ ポリシーは影響を受けず、パッケージ リソースは PackageStore から取得されます。

PackWebRequest.CachePolicy では、 PackageStore の特定の機能により、以下に示すようにポリシーのサブセットがサポートされます。

表 1 PackWebRequest.CachePolicy ポリシー

CachePolicy 説明
BypassCache URI が一致する PackageStore エントリを無視します。
CacheOnly PackageStore エントリのみを考慮してください (サーバーにデータのクエリを実行する WebRequest を作成しないでください)。
CacheIfAvailable PackageStore を検査し、見つかった場合はそこに任意のパッケージを使用します。それ以外の場合は、パッケージ URI ("pack:" URI の内部 URI) によって示されるリソースに対してネットワーク要求を行います。 既定値です。

PackWebRequest の場合、他のすべての CachePolicy 値を設定すると、WebException が作成されます

プログレッシブ読み込み

PackWebRequest は、パッケージが "http:" プロトコル経由でアクセスされると、パッケージ パーツを段階的に読み込むことができます。 プログレッシブ読み込みでは、パッケージ全体がローカルで使用できるようになる前に、アプリケーションがパーツ リソースにアクセスできるようになります。 PackWebRequest のプログレッシブ読み込み機能は自動です。呼び出し元のアプリケーションでは、介入することなくパフォーマンスが向上します。

プログレッシブ読み込みは、"http:" 1.1 プロトコルで定義されているように、リソースの "バイト範囲要求" の作成に基づいています。 ZIP アーカイブ形式では重要な情報がファイルの物理的な末尾にある "中央ディレクトリ" に保持されるため、パッケージを物理的な形式で格納するために使用される ZIP ファイル形式は、このメカニズムの利点があります。

PackWebRequest を使用してパッケージ全体を要求すると、呼び出し元がシークできるストリームの返しが開始されます。 PackWebRequest によって提供されるストリームでパッケージを開くと、呼び出し元は、"http:" プロトコルなどを使用して直接要求を行う場合よりも迅速にパーツを取得できます。

URI の評価と分解のためのサービス

パッケージ クラスによって返されるリレーションシップ パーツ名の識別

Package.GetParts メソッドを使用して取得したパーツのコレクションを管理する場合、リレーションシップ パーツを識別して、他のパーツとは別に処理できるようにします。 PackUriHelper.IsRelationshipPartUri は、パーツがリレーションシップ パーツであるかどうかを識別するために使用されます。

例: PackUriHelper.IsRelationshipPartUri

//Given the URI for a part

Uri partUri = new Uri("/_rels/sports.rels", UriKind.Relative);

bool isRelationshipPart = PackUriHelper.IsRelationshipPartUri(PartUri);

//The resulting isRelationshipPart value is "TRUE"

リレーションシップ パーツ名を操作するために、他の 2 つの PackUriHelper メソッドを使用できます。 PackUriHelper.GetRelationshipPartUri は、ソース パーツ名を指定したリレーションシップ パーツ名を返します。 PackUriHelper.GetSourcePartUriFromRelationshipPartUri は、指定されたリレーションシップ パーツ名のソース パーツ名を返します。

等価性の URI の比較

パッケージを作成または使用するときに、キャッシュを使用してパーツを格納するアプリケーションでは、同等のパーツ名のチェックを実行する必要がある場合があります。 PackUriHelper.ComparePartUri メソッドは、パーツ名の等価性をチェックします。

例: PackUriHelper.ComparePartUri

//Given two part names in the same package
//firstPartName = "/a.xaml"
//secondPartName = "/A.xaml"

//Use PackUriHelper.ComparePartUri to identify if the names 
//are equivalent.

Bool isSamePartName = PackUriHelper.ComparePartUri 
               (firstPartName, secondPartName);

//The resulting isSamePartName value is "TRUE"

2 つの "pack:" URI の構文等価性を確認するには、 PackUriHelper.ComparePackUri メソッドを使用します。

例: PackUriHelper.ComparePackUri

//Given two "pack:" URIs
//firstPackUri =
// "PACK://HTTP%3A,,WWW.NEWSDOCS.COM,local,today.container
// /FILES/FIXEDDOC.XAML"
//secondPackUri = 
// "pack://http%3a,,www.newsdocs.com,local,today.container
// /files/fixeddoc.xaml"

//Use PackUriHelper.ComparePackUri to identify if the same resource 
//is targeted.

bool isSameResource = PackUriHelper.ComparePackUri 
            (firstPackUri, secondPackUri);

//The resulting isSameResource value is "TRUE"

"pack:" URI からのコンポーネント URI の抽出

"pack:" URI からコンポーネント パッケージ URI とパーツ URI を抽出するには、それぞれ PackUriHelper.GetPackageUri メソッドと PackUriHelper.GetPartUri メソッドを使用します。

例: PackUriHelper.GetPackageUri

//Given the "pack:" URI for a package

Uri packUri = "pack://http%3a,,www.newsdocs.com,local,today.container
            /files/abc.xaml";

//Use PackUriHelper.GetPackageUri to obtain the URI of the package

Uri packageUri = new PackUriHelper.GetPackageUri(packUri);

//The resulting packageUri value is
//"http://www.newsdocs.com/local/today.container"

例: GetPartUri の例

//Given the "pack:" URI for a part

Uri packUri = "pack://http%3a,,www.newsdocs.com,local,today.container
         /files/abc.xaml";

//Use PackUriHelper.GetPartUri to obtain the URI of the part

Uri partUri = new PackUriHelper.GetPartUri(packUri);

//The resulting partUri value is "/files/abc.xaml"

リファレンス

Open Packaging Conventions

Uniform Resource Identifier (URI): 一般的な構文

Open XML Paper Specification

国際化されたリソース識別子 (IRI)