Das Adressierungsmodell der Open Packaging Conventions

Veröffentlicht: 31. Jul 2006
Von David Meltzer und Andrey Shur

Dieser Artikel bietet eine Übersicht über das in den Open Packaging Conventions (offengelegte Paketerstellungskonventionen) verwendete Adressierungsmodell. Sie erhalten Informationen darüber, wie Pakete und deren Komponenten adressiert werden, wie relative Verweise in Paketkomponenten aufgelöst werden und wie Anwendungen das Paketadressierungsmodell mithilfe von .NET Framework- und WinFx-Klassen verwenden können. (16 gedruckte Seiten)

Auf dieser Seite

Einleitung Einleitung
Das Adressierungsmodell Das Adressierungsmodell
Programmierunterstützung für "pack:"-URIs Programmierunterstützung für "pack:"-URIs
Referenzartikel Referenzartikel

Einleitung

Microsoft führte die Open Packaging Conventions (in englischer Sprache) als Teil des Entwurfs von Office 2007 und Windows Vista ein. Diese Konventionen beschreiben, wie Inhalte in einem "Paket" organisiert werden können. Zu diesen Inhalten gehören beispielsweise ein Dokument, eine Mediensammlung und eine Anwendungsbibliothek. Pakete fassen alle Inhaltskomponenten in einem einzigen Objekt zusammen.

Ein Textverarbeitungsprogramm kann Pakete beispielsweise dazu verwenden, die Seiten eines Dokuments, die benötigten Schriftarten sowie die in den Seiten enthaltenen Bilder, Diagramme und Anmerkungen zu speichern. Eine Anwendung zur Anzeige oder Verwaltung von Dokumenten kann dann zum Beispiel nur Teile des Inhalts eines Pakets anzeigen. Anwendungen können ein paketbasiertes Format wie die XML Paper Specification (XPS) verwenden, um Inhalt und Ressourcen mit festgelegtem Layout an einen Drucker zu senden.

Dieser Artikel bietet eine Übersicht über das in den Open Packaging Conventions verwendete Adressierungsmodell. Sie erhalten Informationen darüber, wie Pakete und deren Komponenten adressiert werden und wie relative Verweise in Paketkomponenten aufgelöst werden. Außerdem erfahren Sie in diesem Artikel, wie Anwendungen das Paketadressierungsmodell mithilfe von .NET Framework- und WinFx-Klassen verwenden können. Dieser Artikel wurde in erster Linie für Entwickler von Anwendungen geschrieben, die mit Paketen umgehen, diese erstellen oder verarbeiten.

Die vollständigen Regeln, die zur Implementierung des Paketadressierungsmodells benötigt werden, finden Sie in der Spezifikation der Open Packaging Conventions. Weitere Informationen zu den beschriebenen Klassen und Methoden finden Sie in den WinFx- und .NET-SDKs.

Die in dieser Übersicht dargestellten Informationen setzen grundlegende Kenntnisse der URI-Spezifikation voraus. Folgende Begriffe werden gemäß RFC 3986 verwendet: URI, URI-Verweis (URI reference), Schemakomponente (scheme component), Autoritätskomponente (authority component), Pfadkomponente (path component), absoluter Pfad (path-absolute) und relativer Verweis (relative reference). Der Begriff URI meint immer das absolute Format eines URI: die Schemakomponente ist vorhanden, und alle anderen Komponenten entsprechen der schemaspezifischen Syntax. Der hier verwendete Begriff adressierbar bedeutet, dass ein URI vorhanden ist, der eine Ressource kennzeichnet.

Das Adressierungsmodell

Die Open Packaging Conventions definieren ein logisches Modell zur Organisation des Inhalts und der Ressourcen eines Pakets und stellen eine Zuordnung dieses logischen Modells zu einer physischen Darstellung auf Grundlage von ZIP- und XML- sowie weiterer frei verfügbarer Technologien zur Verfügung.

Das durch die Open Packaging Conventions beschriebene logische Paketerstellungsmodell definiert ein abstraktes Paketmodell, das eine Sammlung von Komponenten beinhaltet. Komponenten können in Beziehung zueinander stehen, und das Paket kann über Beziehungen zu Komponenten verfügen. Das Paketerstellungsmodell gibt an, wie die Komponenten in einem Paket benannt werden, wie auf sie verwiesen wird und in welchen Beziehungen sie zueinander stehen. Das durch die Konventionen definierte Adressierungsmodell bildet die Grundlage dafür, dass auf Komponentenressourcen in einem Paket verwiesen werden kann und diese abgerufen werden können.

Adressierbare Paketressourcen

Eine gesamte Paketinstanz ist, wie jede in der Paketinstanz enthaltene Komponente, eine adressierbare Ressource.

Adressieren eines Pakets als Einheit

In Anwendungen kann ein URI mit einem beliebigen Schema (z. B. "http:", "ftp:" usw.) verwendet werden, um ein Paket als Einheit zu adressieren. Dabei erhält die Anwendung den Bitstream, der das gesamte Paket enthält.

Anwendungen können ein Paket außerdem mithilfe des durch die Open Packaging Conventions definierten URI-Schemas "pack:" adressieren. In diesem Schema ist festgelegt, dass der vollständige URI, der auf das Paket verweist, in der Autoritätskomponente eines "pack:"-URI in codierter Form enthalten ist.

Beispiel: Adressieren eines Pakets

In den folgenden Beispielen wird die Paketressource durch einen "http:"- bzw. "pack:"-URI adressiert:

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

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

Der MIME-Typ der erhaltenen Paketressource gibt das Dateiformat des Pakets an – dies kann beispielsweise das XPS-Dokumentformat (.xps), das Office Open XML-Format (.docx) oder ein anderes Format sein, das den Open Packaging Conventions entspricht.

Anwendungen können aus verschiedenen Gründen (z. B. zur Verbesserung der Leistung) einen für ihre Domäne spezifischen URI als Autoritätskomponente eines "pack:"-URI verwenden. Ein derartiger URI kann nur im Kontext einer bestimmten Anwendung aufgelöst werden. Die für solche anwendungsspezifischen URIs verwendete Programmiertechnik wird später im Abschnitt "PackageStore" beschrieben.

Adressieren von Komponenten in einem Paket

Komponenten in einem Paket werden mithilfe von "pack:"-URIs adressiert. Ein "pack:"-URI, der eine Komponente adressiert, hat folgende Struktur: pack://<Autorität><Pfad>

Beispiel: Adressieren von Komponenten

pack://http%3a,,www.site.com,windows,p1.xps/fonts/arial.ttf adressiert die Komponente mit der Bezeichnung /fonts/arial.ttf in dem durch http://www.site.com/windows/p1.xps adressierten Paket.

Die Autoritätskomponente enthält den codierten URI des gesamten Pakets. In der Pfadkomponente ist der Name der Komponente in diesem Paket enthalten. Komponentennamen entsprechen, mit einigen zusätzlichen Einschränkungen ([1], Abschnitt 2.1.1.1), der für den absoluten Pfad definierten Syntax für die URI-Komponente ([2], Abschnitt 3.3).

Beispiel: Komponentennamen

/documents/doc1.xaml

/pages/page4.xaml

/fonts/arial.ttf

Komponentennamen bestehen aus ASCII-Zeichenfolgen, bei denen die Groß-/Kleinschreibung nicht berücksichtigt wird. Alle Komponenten in einem Paket haben eindeutige Namen.

Verwenden von Fragmentbezeichnern zum Verweisen auf Komponenten

Einige Anwendungen, die die Open Packaging Conventions verwenden, können mithilfe eines URI einer Paketeinheit, der kein "pack:"-URI ist, mit formatspezifischen Fragmentbezeichnern auf eine Komponente verweisen.

Beispiel: Verwenden eines URI, der kein "pack:"-URI ist, zum Verweisen auf eine Komponente

Der URI http://www.site.com/windows/p1.xps#15 wird verwendet, um auf die Komponente zu verweisen, die die Seite 15 im Dokument p1.xps darstellt ([3], Abschnitte 9.2.2 und 9.2.3).

Obwohl es zulässig und für bestimmte Szenarios sinnvoll ist, mit URIs, die keine "pack:"-URIs sind, auf Komponenten zu verweisen, können derartige URIs nicht als Basis-URIs zum Auflösen relativer Verweise im Komponenteninhalt verwendet werden.

Verweisen auf Einträge innerhalb von Komponenten

Eine Komponente ist die kleinste adressierbare Ressource in einem Paket. Möglicherweise müssen Anwendungen jedoch auf Einträge im Inhalt von Komponenten verweisen. Bei bestimmten Inhaltstypen kann mithilfe von Fragmentbezeichnern ([2], Abschnitt 3.5) auf Einträge verwiesen werden. In den Open Packaging Conventions sind Fragmentbezeichner nicht spezifiziert. Anwendungen, die Fragmentbezeichner verwenden, sind selbst für deren ordnungsgemäße Verarbeitung verantwortlich.

Beispiel: Auf Einträge innerhalb von Komponenten verweisen

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml#//[@Id="A012"] verweist auf einen Satz von XML-Knoten im Inhalt der Komponente mit dem Namen /pages/page1.xaml, die den Id-Attributwert A012 haben.

Verschachtelte Pakete

Pakete können verschachtelt sein. Eine Komponente in einem Paket kann Inhalt beliebigen Typs enthalten, auch ein gesamtes Paket. Die Komponenten eines verschachtelten Pakets können über einen "pack:"-URI mit einer Autoritätskomponente adressiert werden, die die Komponente angibt, in der dieses verschachtelte Paket enthalten ist ([1], Anhang D.3).

Beispiel: Adressieren von Komponenten in verschachtelten Paketen

Ein Paket unter http://www.site.com/package enthält eine Komponente mit dem Namen /nested-package, die durch den "pack:"-URI pack://http%3a,,www.site.com,package/nested-package adressiert wird.

Die durch den oben angegebenen URI adressierte Komponente enthält eine Paketeinheit, die eine Komponente mit dem Namen /p1.xaml enthält.

Diese Komponente in dem verschachtelten Paket hat folgende Adresse:

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

Verweise im Komponenteninhalt

Komponenten mit bestimmten Inhaltstypen, wie beispielsweise XML, können URI-Verweise enthalten. URI-Verweise können URIs oder relative Verweise sein. URI-Verweise können durch Unicode-Zeichenfolgen im Inhalt dargestellt werden. Anwendungen, die derartige URI-Verweise auflösen, müssen die Zeichenfolgen in ein URI-Format ([4], Abschnitt 3.1) umwandeln.

Ein relativer Verweis ist ein URI, der relativ zum Basis-URI des Inhalts, der den Verweis enthält, ausgedrückt wird. Der Standard-Basis-URI für Komponenteninhalt ist der "pack:"-URI, mit dem die Komponente adressiert wird.

Beispiel: Basis-URI

Eine Komponente mit dem Namen /pages/page1.xaml in einem Paket mit der Adresse http://www.site.com/windows/p1.xps hat folgenden Basis-URI:

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

Wenn zum Auflösen relativer Verweise in den Einträgen des Komponenteninhalts ein alternativer Basis-URI benötigt wird, muss eine Anwendung diesen explizit angeben. Spezielle Inhaltstypen stellen besondere Möglichkeiten zur Angabe des alternativen Basis-URI zur Verfügung. XML verwendet zum Beispiel das xml:base-Attribut, HTML das <base>-Element, und in den Open Packaging Conventions wird das TargetMode-Attribut für Relationship-Elemente verwendet.

Die Verwendung des "pack:"-URI einer Komponente als Basis-URI für einen relativen Verweis gewährleistet, dass die Ressource, auf die verwiesen wird, eine Komponente im selben Paket ist ([2], Abschnitt 5.2), es sei denn, der relative Verweis hat das selten verwendete Format des Netzwerkpfads (d. h., ein relativer Verweis, der mit "//" beginnt).

Beispiel: Auflösen eines relativen Verweises

Der relative Verweis ../../page2.xaml innerhalb der Komponente, die durch pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml adressiert wird, wird zu pack://http%3a,,www.site.com,windows,p1.xps/page2.xaml aufgelöst. Dadurch wird die Komponente /page2.xaml adressiert.

Paketersteller können Komponentennamen als gültige Form von relativen Verweisen verwenden. Wenn Paketersteller Komponentennamen als relative Verweise verwenden, sollten sie jedoch überlegen, ob die Komponenten, auf die verwiesen wird, nicht auch als extrahierte Ressourcen außerhalb des Pakets adressiert werden können. Sobald Komponenten aus einem Paket extrahiert wurden, werden Komponentennamen, die als relative Verweise verwendet werden, möglicherweise nicht wie erwartet aufgelöst. Der obligatorische führende Schrägstrich für Komponentennamen, der in der Syntax für Komponentennamen festgelegt ist, impliziert, dass solche relativen Verweise vom Stamm der aktuellen Autorität aus aufgelöst werden.

Beispiel: Adressieren extrahierter Ressourcen

Im Inhalt einer Komponente mit dem Namen /doc1/pages/page1.xaml adressiert der relative Verweis /page2.xaml die Komponente /page2.xaml und der relative Verweis ./page3.xaml die Komponente /doc1/pages/page3.xaml.

Nachdem die Komponenten /doc1/pages/page1.xaml, /doc1/pages/page3.xaml und /part2.xaml aus dem Paket in die Dateien file:///c:/mydocs/doc1/pages/page1.xaml, file:///c:/mydocs/doc1/pages/page3.xaml bzw. file:///c:/mydocs/page2.xaml extrahiert wurden, adressiert der relative Verweis ./page3.xaml erwartungsgemäß die Datei file:///c:/mydocs/doc1/pages/page3.xaml. Der relative Verweis /page2.xaml adressiert jetzt jedoch die Datei file:///page2.xaml.

Relative Verweise in Beziehungen

Die Open Packaging Conventions definieren Verbindungen zwischen Quell- und Zielkomponenten in einem Paket als Beziehungen ([1], Abschnitt 1.3).

Beziehungen werden ihren Quellen entsprechend gruppiert und gespeichert. Eine Beziehungskomponente enthält Beziehungen, die aus derselben Quellkomponente stammen. Jede Beziehung wird durch ein XML-Element im Inhalt dieser Beziehungskomponente beschrieben. Die Beziehungskomponente ist unter Verwendung einer definierten Benennungskonvention für diese Komponente ausschließlich mit dieser Quellkomponente verknüpft (und umgekehrt).

Der Standard-Basis-URI für die im Relationship-Element angegebenen URIs ist der "pack:"-URI der Quellkomponente ([1], Abschnitt 1.3.5). Das TargetMode-Attribut eines Relationship-Elements gibt den Basis-URI für die festgelegte Beziehung an.

Beispiel: "Relationship"-Element

Das Element in der Beziehungskomponente, die eine Beziehung von einer Quellkomponente mit dem Namen /pages/page1.xaml zu der Zielkomponente /fonts/arial.ttf im selben Paket definiert, kann folgendermaßen aussehen:

<Relationship Type="http://schemas.microsoft.com/xps/2005/06/restricted-font" TargetMode="Internal" Id="A123" Target="../fonts/arial.ttf"/>

Der Internal-Wert des TargetMode-Attributs gibt an, dass als Standard für den Inhalt der Beziehungskomponente der Basis-URI für das Relationship-Element verwendet wird – und dieser ist derselbe "pack:"-URI, der auch für die Quellbeziehungskomponente verwendet wird. Im vorhergehenden Beispiel ist der Basis-URI für das Relationship-Element der "pack:"-URI der Komponente /pages/page1.xaml.

Beziehungen können sich auch auf externe Ressourcen, relativ zum Speicherort des gesamten Pakets, beziehen.

Beispiel: Beziehung zu einem externen Ziel

Für ein Paket, das sich unter file:///c:/office12/sample.docx befindet, definiert das XML-Element

<Relationship Id="rId9" Type="http://schemas.microsoft.com/office/2006/relationships/image" Target="Icon.JPG" TargetMode="External"/>

die Beziehung zu der Datei file:///c:/office12/icon.jpg

Der External-Wert des TargetMode-Attributs gibt an, dass sich die Beziehung auf eine Ressource außerhalb des Pakets beziehen muss. Wenn das Target-Attribut einen relativen Verweis enthält, ist ein Basis-URI erforderlich. Der Basis-URI für dieses Relationship-Element muss der URI des gesamten Pakets sein.

Delegieren von Verweisen an Beziehungen

Einige Formate auf der Grundlage von Paketen können das Verwenden von URI-Verweisen im Inhalt vermeiden, indem sie Verweise an Beziehungen delegieren. Diese Delegierungstechnik basiert auf der Verwendung eindeutiger Id-Werte für jedes Relationship-Element, um relative Verweise im Komponenteninhalt zugehörigen Beziehungen zuzuordnen.

Beispiel: Zuordnen von relativen Verweisen im Komponenteninhalt zu Beziehungen

Ein Paket, das sich unter file:///c:/office12/sample.docx befindet, enthält eine Komponente namens /word/document.xml, die über folgenden Eintrag verfügt:

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

Die mit dieser Komponente verknüpfte Beziehungskomponente enthält das Element

<Relationship Id="rId6" Type="http://schemas.microsoft.com/office/2006/relationships/image" TargetMode="Internal" Target="media/image1.jpeg"/>.

Dadurch wird das Element mit der Komponente /word/media/image1.jpeg verknüpft.

Der Vorteil diese Ansatzes besteht darin, dass eine Anwendung alle Verweise innerhalb eines Pakets erkennen und verwalten kann, ohne den Inhalt der Komponenten untersuchen zu müssen.

Wenn Verweise an Beziehungen delegiert werden, funktionieren Paketkomponenten, die in einzelne Dateien extrahiert werden, allerdings möglicherweise nicht ordnungsgemäß. Damit die Ziele von Beziehungen nach dem Extrahieren weiterhin verwendet werden können, muss eine verarbeitende Anwendung über spezielle Kenntnisse über Beziehungen, die Open Packaging Conventions zur Benennung von Beziehungskomponenten und die Definition von Basis-URIs für Beziehungsdateien verfügen.

Programmierunterstützung für "pack:"-URIs

Anwendungen, die Pakete erstellen und/oder verarbeiten, können mit Paket- oder Komponentenadressen arbeiten und relative Verweise innerhalb der Komponenten auflösen. WinFx, die von Microsoft bereitgestellte nächste Generation von verwalteten APIs, enthält Klassen, die das Adressierungsmodell der Open Packaging Conventions unterstützen. Mit diesen Klassen können Anwendungen Verweise zusammenstellen und analysieren sowie Paketressourcen abrufen. Die Verwendung der Klasse PackUriHelper vereinfacht den Umgang mit "pack:"-URIs. Die PackWebRequest-Klasse dient zum Abrufen von Ressourcen, die durch "pack:"-URIs adressiert werden.

In diesem Abschnitt werden die Funktionen erläutert, die von diesen Diensten zum Zusammenstellen, Analysieren und Auflösen von Verweisen ausgeführt werden.

Ermöglichen des Zugriffs auf die Paketdienste

Das .NET Framework Version 3.0 (oder höher) muss zum Verwenden der Paketerstellungsdienstklassen installiert sein. Die Klassen befinden sich im Namespace System.IO.Packaging.

Beispiel: Registrieren des "pack:"-URI-Schemas

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

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

Abrufen des "pack:"-URI einer Zielressource

Beim Verarbeiten eines Pakets kann das vollständige Paket oder lediglich eine Komponente als Objekt abgerufen werden. In jedem Fall kann die PackUriHelper.Create-Methode zum Erstellen des "pack:"-URI des Pakets oder der Komponente verwendet werden. Dieser "pack:"-URI wird anschließend der PackWebRequest-Methode zum Abrufen der Ressource übergeben. PackWebRequest wird im nächsten Abschnitt "Abrufen von Paketressourcen mit PackWebRequest" ausführlicher behandelt.

In den folgenden Schritten wird ausführlich ein gebräuchliches Beispiel zum Verwenden der Klassen PackUriHelper und PackWebRequest zum Unterstützen der Paketverarbeitung erläutert. Wenn die URIs eines Pakets und einer Komponente bekannt sind, kann eine Anwendung:

  1. einen "pack:"-URI aus dem Paket-URI und dem Komponenten-URI mit PackUriHelper zusammenstellen.

  2. einen Bitstream durch Aufrufen von PackWebRequest erhalten.

  3. den Inhalt der Komponente laden und zum Abrufen von relativen Verweisen analysieren.

  4. diese relativen Verweise in Bezug auf den Basis-URI der Komponente auflösen (der in Schritt 1 zusammgestellte "pack:"-URI).

  5. System.Uri zum Auflösen der relativen Verweise und PackWebRequest zum Abrufen der angegebenen Ressourcen verwenden.

Erstellen eines "pack:"-URI für ein bestimmtes Paket

Der "pack:"-URI des Pakets kann mit der Methode PackUriHelper.Create erstellt werden.

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

Der erstellte "pack:"-URI wird der PackWebRequest-Methode zum Abrufen der Paketressource übergeben.

Erstellen eines "pack:"-URI für eine bestimmte Komponente

Der "pack:"-URI der Komponente kann mit der Methode PackUriHelper.Create erstellt werden.

Beispiel: 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"

Der erstellte "pack:"-URI wird der PackWebRequest-Methode zum Abrufen der Komponentenressource übergeben.

Auflösen von relativen Verweisen

Beim Verarbeiten des Inhalts einer Komponente können relative Verweise auf andere Komponenten oder Ressourcen auftreten. Das Auflösen dieser Verweise ist ein erster Schritt zum Abrufen der angegebenen Ressourcen.

Ein relativer Verweis im Inhalt einer Komponente wird auf Grundlage des Basis-URI einer Komponente in Bezug auf den "pack:"-URI der Zielkomponente aufgelöst. Der "pack:"-URI der Zielkomponente wird an PackWebRequest übergeben, um die Komponentenressource aus dem Paket abzurufen. Der Name einer Zielkomponente, abgeleitet von dem "pack:"-URI der Zielkomponente, kann ebenfalls zum Abrufen einer Komponente verwendet werden, indem er an die Package.GetPart-Methode übergeben wird.

Beim Auflösen von relativen Verweisen auf Zielkomponenten können mehrere Pfade zur Auflösung verwendet werden, abhängig von den beim Starten verfügbaren Informationen und abhängig davon, ob das Paket geöffnet ist (oder geöffnet werden kann). Zwei dieser Pfade können sein:

  • Beim Starten:

    1. Der "pack:"-URI der den Verweis beinhaltenden Komponente ist bekannt.

    2. Das Paket ist nicht geöffnet.

    //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.
    
    
  • Beim Starten:

    1. Der Name der den Verweis beinhaltenden Komponente ist bekannt.

    2. Das Paket ist geöffnet.

    //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);
    
    
Bereitstellen von Komponentennamen für die Paketklasse

Nach dem Öffnen eines Pakets steht die Package-Klasse zum Hinzufügen, Abrufen und Entfernen von Komponenten zur Verfügung. Methoden der Package-Klasse, bspw. Package.AddPart, Package.DeletePart und Package.GetPart, übernehmen einen Komponenten-URI als Parameter. Die PackUriHelper.CreatePartUri-Methode kann zum Erstellen eines gültigen Komponentennamens aus einem relativen Verweis zum Basis-URI des Pakets verwendet werden.

Beispiel: 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"

Dienst zum Erstellen von relativen Verweisen

Eine Entwicklungsanwendung muss möglicherweise einen relativen Verweis ableiten, der nach dem Ablegen im Inhalt einer Quellkomponente auf eine Zielkomponente zeigt. Die GetRelativeUri-Methode erfüllt diesen Zweck.

Beispiel: 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"

Abrufen von Paketressourcen mit PackWebRequest

Anwendungen können Paket- oder Komponentenressourcen mit PackWebRequest abrufen, einer von System.Net.WebRequest abgeleiteten Klasse. PackWebRequest gibt eine Ressource zurück, die über einen vorgegebenen "pack:"-URI adressiert wird.

Im Allgemeinen besteht das Initiieren von PackWebRequest für einen "pack:"-URI aus folgenden Schritten:

  1. Die Syntax des "pack:"-URI wird überprüft.

  2. Die Autoritätskomponente wird aus dem "pack:"-URI extrahiert und auf Übereinstimmung mit der Syntax eines absoluten URI überprüft.

  3. Wenn die Pfadkomponente des "pack:"-URI leer ist:

    • Der Paketstream wird für die Autoritätskomponente abgerufen und an den Aufrufer zurückgegeben.

      Wenn die Pfadkomponente nicht leer ist:

      1. Das Paket wird für die Ressource abgerufen, die durch die Autoritätskomponente angegeben wurde. Abhängig von der Festlegung der CachePolicy ruft PackWebRequest das Paket entweder vom PackageStore ab oder erzeugt einen internen WebRequest für die Paketressource und öffnet das Paket aus dem zurückgegebenen Paketstream.

      2. Die Komponente wird unter Verwendung der Pfadkomponente des "pack:"-URI als Komponentenname abgerufen.

      3. Der Komponentenstream wird abgerufen und an den Aufrufer zurückgegeben.

PackWebResponse.GetStream gibt einen Bitstream zurück, der entweder das vollständige Paket (einen Paketstream) oder eine einzelne Komponente des Pakets (einen Komponentenstream) darstellt.

Im Gegensatz zu den meisten WebResponse-Streams kann ein Paketstream über Stream.Seek durchsucht werden. Ein Paketstream kann zum Erstellen eines Paketobjekts verwendet werden.

Beim Arbeiten mit Paketressourcen über das HTTP-Protokoll unterstützt PackWebRequest ein progressives Laden von Komponenten: die Fähigkeit zum Abrufen von Komponentenressourcen in beliebiger Reihenfolge, ohne alle Paketdaten bis hin zu den Komponentendaten zu laden.

PackWebRequest bietet lediglich Möglichkeiten zum Verarbeiten von Ressourcen. Sie kann nicht zum Bereitstellen oder Senden von Daten an einen Server verwendet werden.

PackWebRequest unterstützt derzeit weder asynchrone Vorgänge (wie beispielsweise BeginGetResponse) noch verschachtelte Pakete (diese wurden bereits in "Adressieren von Komponenten in einem Paket" beschrieben).

PackageStore

Beim Laden von Paketen, die Komponenten mit zahlreichen Verweisen auf andere Komponenten enthalten, kann durch Verwenden von PackageStore die Antwortzeit für Ressourcenanfragen verbessert und die Netzwerkbelastung verringert werden. PackageStore ist ein anwendungsspezifisches Dictionary für Verweise auf geöffnete Pakete. Jedes im PackageStore registrierte Paket wird über einen URI-Schlüsselwert angesprochen.

PackWebRequest kann über PackageStore bei Bedarf Ressourcen aus einem Paket abrufen, ohne jedes Mal eine Serveranfrage auszuführen, wenn eine weitere Ressource aus diesem Paket benötigt wird.

Der PackageStore wird nicht automatisch nach einem Aufruf von PackWebRequest aktualisiert – er muss ausdrücklich geändert werden. Zum Hinzufügen oder Entfernen von Verweisen auf geöffnete Pakete im PackageStore stehen zwei öffentliche Methoden zur Verfügung: Package.AddPackage und Package.RemovePackage.

Die für PackWebRequest festgelegte Standardcacherichtlinie (CacheIfAvailable) weist die Klasse an, den PackageStore zum Abrufen des Pakets zu verwenden. PackWebRequest kann beim Abrufen von Ressourcen zum Ignorieren des Inhalts von PackageStore gezwungen werden, indem die Cacherichtlinie auf BypassCache festgelegt wird. Dies wird im nächsten Abschnitt "Cacherichtlinien" beschrieben.

Beim Abrufen der Bits eines Pakets oder einer Komponente entsprechend der Standardcacherichtlinie überprüft PackWebRequest zunächst den PackageStore auf Vorhandensein eines registrierten Pakets mit einem Schlüssel, der der Autoritätskomponente des "pack:"-URI entspricht. Wenn PackageStore das Paket für diesen Schlüssel nicht enthält, erstellt PackWebRequest einen internen WebRequest zum Herunterladen der Ressource unter Verwendung der Autoritätskomponente im "pack:"-URI.

Cacherichtlinien

Cacherichtlinien definieren die Regeln zum Ermitteln, ob eine Ressourcenanfrage durch eine zwischengespeicherte Kopie der Ressource bedient werden kann.

Beim Verwenden von PackWebRequest können zwei Ebenen von Cacherichtlinien ausdrücklich festgelegt werden. Eine Cacherichtlinie kann für PackWebRequest selbst zum Steuern der Interaktion mit PackageStore festgelegt werden. Eine weitere Cacherichtlinie kann für den Cache, der von einem internen WebRequest gesteuert wird, festgelegt werden. Auf den internen WebRequest kann über PackWebRequest mit PackWebRequest.GetInternalRequest() zugegriffen werden.

Die für den internen WebRequest festgelegte Cacherichtlinie hat keine Auswirkung, wenn PackWebRequest.CachePolicy auf CacheOnly gesetzt wurde und deshalb die Paketressource aus dem PackageStore abgerufen wird.

PackWebRequest.CachePolicy unterstützt eine Untermenge von Richtlinien (die im Folgenden dargestellt werden) in Bezug auf die besonderen Möglichkeiten des PackageStore.

Tabelle 1: Richtlinien für PackWebRequest.CachePolicy

CachePolicy

Beschreibung

BypassCache

Ignorieren von PackageStore-Einträgen bei übereinstimmendem URI.

CacheOnly

Ausschließliches Verwenden von PackageStore-Einträgen (kein Erstellen eines WebRequest zum Abfragen des Servers).

CacheIfAvailable

Überprüfen des PackageStore und Verwenden der vorgefundenen Pakete; andernfalls Ausführen einer Netzwerkanfrage für die Ressource, die durch den Paket-URI (den internen URI des "pack:"-URI) angegeben wurde. Dies ist die Standardeinstellung.

Das Festlegen anderer CachePolicy-Werte führt bei PackWebRequest zum Auslösen einer WebException.

Progressives Laden

PackWebRequest ermöglicht das progressive Laden einer Paketkomponente, wenn auf das Paket über das HTTP-Protokoll zugegriffen wird. Das progressive Laden ermöglicht Anwendungen den Zugriff auf Komponentenressourcen, bevor das vollständige Paket lokal verfügbar ist. Das progressive Laden von PackWebRequest ist ein automatisches Feature: die aufrufende Anwendung kann die verbesserte Leistung direkt nutzen.

Das progressive Laden basiert auf im HTTP-Protokoll Version 1.1 definierten "byte-range requests" für Ressourcen. Das ZIP-Dateiformat, das zum physischen Speichern von Paketen verwendet wird, profitiert von diesem Mechanismus, da das ZIP-Archivformat wichtige Informationen in einem "zentralen Verzeichnis" am Ende der Datei speichert.

Nach dem Abfragen eines vollständigen Pakets durch PackWebRequest beginnt der Dienst mit dem Zurückgeben eines Streams, der von einem Aufrufer durchsucht werden kann. Wird ein Paket aus dem von PackWebRequest übermittelten Stream geöffnet, kann der Aufrufer Komponenten, im Vergleich zu direkten Abfragen (beispielsweise über das HTTP-Protokoll), schneller abrufen.

Dienste zum Auswerten und Zerlegen von URIs
Ermitteln der Namen für die von der Paketklasse zurückgegebenen Beziehungskomponenten

Beim Verwalten einer Sammlung von Komponenten, die über die Package.GetParts-Methode abgerufen wurde, können Beziehungskomponenten ermittelt und daher unabhängig von anderen Komponenten verarbeitet werden. Mit PackUriHelper.IsRelationshipPartUri wird ermittelt, ob eine Komponente eine Beziehungskomponente ist.

Beispiel: 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"

Zwei weitere PackUriHelper-Methoden stehen zum Arbeiten mit den Namen für Beziehungskomponenten zur Verfügung. PackUriHelper.GetRelationshipPartUri gibt nach Angabe des Namens einer Quellkomponente den Namen einer Beziehungskomponente zurück. PackUriHelper.GetRelationshipPartUri gibt nach Angabe des Namens einer Beziehungskomponente den Namen der Quellkomponente zurück.

Vergleichen von URIs auf Gleichwertigkeit

Eine Anwendung, die zum Erstellen oder Verarbeiten von Komponenten einen Zwischenspeicher für Komponenten verwendet, muss möglicherweise Überprüfungen von gleichen Komponentennamen durchführen. Die PackUriHelper.ComparePartUri-Methode überprüft die Gleichwertigkeit von Komponentennamen.

Beispiel: 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"

Die PackUriHelper.ComparePackUri-Methode wird zum Ermitteln der lexikalischen Gleichwertigkeit von zwei "pack:"-URIs verwendet.

Beispiel: 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"

Extrahieren von Komponenten-URIs aus einem "pack:"-URI

Zum Extrahieren des Komponentenpaket-URI und des Komponenten-URI aus einem "pack:"-URI werden die Methoden PackUriHelper.GetPackageUri und PackUriHelper.GetPartUri verwendet.

Beispiel: 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"

Beispiel: GetPartUri Example

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

Referenzartikel

Open Packaging Conventions

Uniform Resource Identifier (URI): Generic Syntax

Open XML Paper Specification

Internationalized Resource Identifiers (IRIs)


Anzeigen: