Das Adressierungsmodell der Open Packaging-Konventionen
David Meltzer und Andrey Shur
Microsoft Corporation
Juni 2006
Gilt für:
Open Packaging Conventions
Microsoft Office 2007
Microsoft Windows Vista
Microsoft .NET Framework
Zusammenfassung: Dieser Artikel bietet eine Übersicht über das Adressierungsmodell, das in den Open Packaging Conventions verwendet wird, einschließlich der Behandlung von Paketen und deren Teilen, der Auflösung relativer Verweise in Paketteilen und der Verwendung des Paketadressierungsmodells mithilfe der .NET Framework und Klassen. (16 gedruckte Seiten)
Inhalte
Einleitung
Das Adressierungsmodell
Programmierunterstützung für "pack:"-URIs
Referenzen
Einleitung
Im Rahmen des Entwurfs von Office 2007 und Windows Vista hat Microsoft die Open Packaging Conventions eingeführt. Diese Konventionen beschreiben, wie Inhalte in einem "Paket" organisiert werden können. Einige Beispiele für Inhalte sind ein Dokument, eine Sammlung von Medien und eine Anwendungsbibliothek. Pakete aggregieren alle Komponenten des Inhalts in einem einzelnen Objekt.
Eine Textverarbeitungsanwendung kann Beispielsweise Pakete verwenden, um die Seiten eines Dokuments, die benötigten Schriftarten und die Bilder, Diagramme und Anmerkungen auf den Seiten zu speichern. Eine Dokumentanzeige- oder Verwaltungsanwendung zeigt möglicherweise nur Teile des Inhalts in einem Paket an. Anwendungen können ein paketbasiertes Format wie die XML Paper Specification (XPS) verwenden, um Inhalte und Ressourcen mit festgelegtem Layout an einen Drucker zu senden.
Dieser Artikel bietet eine Übersicht über das Adressierungsmodell, das in den Open Packaging-Konventionen verwendet wird, einschließlich der Adressierung von Paketen und der zugehörigen Teile und der Auflösung relativer Verweise in Paketteilen. In diesem Artikel wird auch erläutert, wie Anwendungen das Paketadressierungsmodell mithilfe der Klassen .NET Framework und .NET Framework 3.0 verwenden können. Dieser Artikel richtet sich in erster Linie an Entwickler von Anwendungen, die Pakete verarbeiten, produzieren oder nutzen.
Vollständige normative Informationen, die zum Implementieren des Paketadressierungsmodells erforderlich sind, finden Sie in der Spezifikation für die Open Packaging Conventions. Die .NET Framework 3.0- und .NET-SDKs bieten weitere Informationen zu den beschriebenen Klassen und Methoden.
Das in dieser Übersicht dargestellte Material setzt grundlegende Kenntnisse der URI-Spezifikation voraus. Die folgenden Begriffe werden gemäß RFC 3986 verwendet: URI, URI-Referenz, Schemakomponente, Autoritätskomponente, Pfadkomponente, Pfad absolut und relative Referenz. Der Begriff URI bezeichnet immer die absolute Form eines URI – die Schemakomponente ist vorhanden, und alle anderen Komponenten entsprechen der schemaspezifischen Grammatik. Der Begriff adressierbar, wie hier verwendet, gibt an, dass ein URI vorhanden ist, der eine Ressource identifiziert.
Das Adressierungsmodell
Die Open Packaging Conventions definieren ein logisches Modell zum Organisieren der Inhalte und Ressourcen eines Pakets und stellen eine Zuordnung von diesem logischen Modell zu einer physischen Darstellung bereit, die auf ZIP, XML und anderen offen verfügbaren Technologien basiert.
Das logische Paketmodell , das von den Open Packaging Conventions beschrieben wird, definiert eine Paketstraktion, die eine Sammlung von Teilen enthält. Teile können Beziehungen zueinander aufweisen, und das Paket kann Beziehungen zu Teilen aufweisen. Das Paketmodell gibt an, wie die Teile in einem Paket benannt, referenziert und verknüpft sind. Das durch die Konventionen definierte Adressierungsmodell ist die Grundlage für den Verweis auf Und Abrufen von Teilressourcen in einem Paket.
Adressierbare Paketressourcen
Ein Paket instance als Ganzes ist eine adressierbare Ressource, ebenso wie jeder Teil im Paket instance.
Adressieren eines Pakets als Einheit
Anwendungen können einen URI mit einem beliebigen Schema (z. B. "http:", "ftp:" usw.) verwenden, um ein Paket als Einheit zu adressieren und den Datenstrom von Bits zu erfassen, die das gesamte Paket umfassen.
Anwendungen können ein Paket auch mithilfe des von den Open Packaging-Konventionen definierten URI-Schemas "pack:" angehen. Dieses Schema gibt an, dass der vollständige URI, der das Paket identifiziert, in der Autoritätskomponente eines "pack:"-URI in einer codierten Form gespeichert wird.
Beispiel: Adressieren eines Pakets
Die Paketressource wird in den folgenden Beispielen durch die URIs "http:" und "pack:" adressiert:
pack://http%3a,,www.site.com,windows,p1.xps/
Der MIME-Typ der abgerufenen Paketressource gibt das Dateiformat des Pakets an. Dies kann z. B. das XPS-Dokumentformat (XPS-Dokumentformat, XPS), das Office Open XML-Format (.docx) oder ein anderes Format sein, das den Open Packaging-Konventionen entspricht.
Aus verschiedenen Gründen (z. B. der Verbesserung der Leistung) können Anwendungen einen domänenspezifischen URI als Autoritätskomponente eines "pack:"-URI verwenden. Ein solcher URI kann nur im Kontext einer bestimmten Anwendung aufgelöst werden. Die Programmiertechnik, die für solche anwendungsspezifischen URIs verwendet wird, wird später in "PackageStore" beschrieben.
Adressieren von Teilen innerhalb eines Pakets
Teile in einem Paket werden mithilfe von "pack:"-URIs adressiert. Die Struktur eines "pack:"-URI, der ein Teil adressiert, lautet wie folgt: pack://< Authority-Pfad><>
Beispiel: Adressieren von Teilen
pack://http%3a,,www.site.com,windows,p1.xps/fonts/arial.ttf adressiert den Teil mit dem Namen /fonts/arial.ttf im Paket adressiert von http://www.site.com/windows/p1.xps.
Die Autoritätskomponente enthält den codierten URI des gesamten Pakets. die Pfadkomponente enthält den Namen des Teils in diesem Paket. Teilenamen entsprechen der für die pfad absolute URI-Komponente ([2], Abschnitt 3.3) definierten Grammatik mit einigen zusätzlichen Einschränkungen ([1], Abschnitt 2.1.1.1).
Beispiel: Teilenamen
/documents/doc1.xaml
/pages/page4.xaml
/fonts/arial.ttf
Bei Teilenamen handelt es sich um ASCII-Zeichenfolgen, bei denen die Groß-/Kleinschreibung nicht beachtet wird. Alle Teile in einem Paket haben eindeutige Namen.
Verwenden von Fragmentbezeichnern zum Verweisen auf Teile
Einige Anwendungen, die die Open Packaging-Konventionen verwenden, können auf einen Teil verweisen, indem sie einen nicht-"pack:"-URI einer Paketeinheit mit formatspezifischen Fragmentbezeichnern verwenden.
Beispiel: Verwenden eines Nicht-"pack:"-URI zum Verweisen auf ein Teil
Der URI http://www.site.com/windows/p1.xps\#15 wird verwendet, um auf den Teil zu verweisen, der Seite 15 im Dokument p1.xps ([3], Abschnitte 9.2.2 und 9.2.3) darstellt.
Obwohl es gültig und für bestimmte Szenarien nützlich ist, dass nicht"pack:"-URIs auf Teile verweisen, können solche URIs nicht als Basis-URIs verwendet werden, um relative Verweise im Teilinhalt aufzulösen.
Verweisen auf Einträge innerhalb von Teilen
Ein Teil ist die präziseste adressierbare Ressource innerhalb eines Pakets. Anwendungen müssen jedoch möglicherweise auf Einträge innerhalb des Inhalts eines Teils verweisen. Für bestimmte Inhaltstypen kann mithilfe von Fragmentbezeichnern auf Einträge verwiesen werden ([2], Abschnitt 3.5). Die Open Packaging-Konventionen geben keine Fragmentbezeichner an. Anwendungen, die Fragmentbezeichner verwenden, sind für die ordnungsgemäße Verarbeitung verantwortlich.
Beispiel: Verweisen auf Einträge innerhalb von Teilen
pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml#///[@Id="A012"] bezieht sich auf einen Satz von XML-Knoten innerhalb des Inhalts des Teils mit dem Namen /pages/page1.xaml und mit dem Id-Attributwertvon A012.
Geschachtelte Pakete
Pakete können geschachtelt werden. Ein Teil in einem Paket kann Inhalte eines beliebigen Typs enthalten, einschließlich eines ganzen Pakets. Die Teile eines geschachtelten Pakets können durch einen "pack:"-URI mit einer Autoritätskomponente adressiert werden, die den Teil mit diesem geschachtelten Paket angibt ([1], Anhang D.3).
Beispiel: Adressieren von Teilen in geschachtelten Paketen
Ein Paket befindet sich unter http://www.site.com/package enthält einen Teil namens /nested-package.
,
adressiert durch das "pack:"- URI-Paket://http%3a,,www.site.com,package/nested-package.
Der vom vorherigen URI adressierte Teil enthält eine Paketeinheit, die einen Teil mit dem Namen /p1.xaml enthält.
Die Adresse dieses Teils im geschachtelten Paket lautet wie folgt:
pack://pack%3a,,http:%253a%2c%2cwww.site.com%2cpackage,nested-package/p1.xaml.
Verweise im Teilinhalt
Teile mit bestimmten Inhaltstypen, z. B. XML, können URI-Verweise enthalten. URI-Verweise können URIs oder relative Verweise sein. URI-Verweise können im Inhalt durch Unicode-Zeichenfolgen dargestellt werden. Anwendungen, die solche URI-Verweise auflösen, müssen die Zeichenfolgen in ein URI-Formular konvertieren ([4], Abschnitt 3.1).
Ein relativer Verweis ist ein URI, der relativ zum Basis-URI des Inhalts ausgedrückt wird, der den Verweis enthält. Der Standard-Basis-URI für Teileinhalte ist der "pack:"-URI, der das Teil adressiert.
Beispiel: Basis-URI
Der Basis-URI für einen Teil mit dem Namen /pages/page1.xaml in einem Paket, das von adressiert wird http://www.site.com/windows/p1.xps , lautet wie folgt:
pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml.
Wenn ein alternativer Basis-URI erforderlich ist, um relative Verweise in den Einträgen des Teileinhalts aufzulösen, muss eine Anwendung den alternativen explizit angeben. Bestimmte Inhaltstypen machen bestimmte Möglichkeiten zur Angabe des alternativen Basis-URI verfügbar. Xml verwendet beispielsweise das xml:base-Attribut , HTML das <Basiselement> und die Open Packaging Conventions verwenden das TargetMode-Attribut für Beziehungselemente .
Die Verwendung des "pack:"-URI eines Teils als Basis-URI für einen relativen Verweis garantiert, dass die referenzierte Ressource teil desselben Pakets ist ([2], Abschnitt 5.2), es sei denn, der relative Verweis befindet sich im selten verwendeten Netzwerkpfadformular (d. h. ein relativer Verweis, der mit "//") beginnt.
Beispiel: Auflösen eines relativen Verweises
Der relative Verweis .. /.. /page2.xaml innerhalb des als pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml adressierten Teils wird aufgelöst, um den Teil mit dem Namen /page2.xaml zu pack://http%3a,,www.site.com,windows,p1.xps/page2.xaml zu packen.
Pakethersteller können Teilenamen als gültige Form von relativen Verweisen verwenden. Bei der Verwendung von Teilenamen als relative Verweise sollten Hersteller jedoch prüfen, ob referenzierte Teile auch als extrahierte Ressourcen außerhalb des Pakets behandelt werden können. Nachdem Teile aus einem Paket extrahiert wurden, werden Teilenamen, die als relative Verweise verwendet werden, möglicherweise nicht wie erwartet aufgelöst. Der obligatorische führende Schrägstrich für Teilenamen, der durch die Teilnamengrammatik angegeben wird, impliziert, dass solche relativen Verweise aus dem Stamm der aktuellen Autorität aufgelöst werden.
Beispiel: Adressieren extrahierter Ressourcen
Im Inhalt eines Teils mit dem Namen /doc1/pages/page1.xaml adressieren die relative Referenz /page2.xaml den Teil mit dem Namen /page2.xaml, und der relative Verweis ./page3.xaml adressieren den Teil mit dem Namen /doc1/pages/page3.xaml.
Nachdem die Teile /doc1/pages/page1.xaml, /doc1/pages/page3.xaml und /part2.xaml aus dem Paket in Dateien mit dem Namen file:///c:/mydocs/doc1/pages/page1.xaml, file:///c:/mydocs/doc1/pages/page3.xaml und file:///c:/mydocs/page2.xaml extrahiert wurden, adressiert der relative Verweis ./page3.xaml die Datei file:///c:/mydocs/doc1/pages/page3.xaml, was erwartet wird; der relative Verweis /page2.xaml adressieren jetzt jedoch die Datei mit dem Namen file:///page2.xaml.
Relative Verweise in Beziehungen
Die Open Packaging Conventions definieren Verbindungen zwischen Quell- und Zielteilen in einem Paket als Beziehungen ([1], Abschnitt 1.3).
Beziehungen werden basierend auf ihren Quellen gruppiert und gespeichert. Ein Beziehungsteil enthält Beziehungen, die aus demselben Quellteil stammen. Jede Beziehung wird durch ein XML-Element innerhalb des Inhalts dieses Beziehungsteils beschrieben. Der Beziehungsteil wird diesem Quellteil eindeutig zugeordnet (und umgekehrt), indem eine definierte Benennungskonvention für den Beziehungsteil verwendet wird.
Der Standard-Basis-URI für die URIs, die in jedem Relationship-Element angegeben sind, ist der "pack:"-URI des Quellteils ([1], Abschnitt 1.3.5). Das TargetMode-Attribut eines Relationship-Elements gibt den Basis-URI für die angegebene Beziehung an.
Beispiel: Beziehungselement
Das Element im Beziehungsteil, das eine Beziehung von einem Quellpart mit dem Namen /pages/page1.xaml zum Zielteil /fonts/arial.ttf innerhalb desselben Pakets definiert, kann wie folgt aussehen:
<Beziehungstyp="https://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 der Basis-URI für das Relationship-Element der Standard für den Inhalt des Beziehungsteils ist – und derselbe wie der "pack:"-URI des Beziehungsquellteils. Im vorherigen Beispiel ist der Basis-URI für das Relationship-Element der "pack:"-URI des Teils /pages/page1.xaml .
Beziehungen können auch externe Ressourcen relativ zum Speicherort des gesamten Pakets verwenden.
Beispiel: Beziehung zum externen Ziel
Für ein Paket, das sich unter file:///c:/office12/sample.docxbefindet, ist das XML-Element
<Beziehungs-ID="rId9"
Type="https://schemas.microsoft.com/office/2006/relationships/image"
Target="Icon.JPG" TargetMode="External"/>
definiert die Beziehung, die auf die Datei file:///c:/office12/icon.jpgausgerichtet ist.
Der External-Wert des TargetMode-Attributs gibt an, dass die Beziehung auf eine Ressource außerhalb des Pakets abzielen muss. Wenn das Target-Attribut einen relativen Verweis enthält, ist ein Basis-URI erforderlich. Der Basis-URI für dieses Beziehungselement muss der URI des gesamten Pakets sein.
Delegieren von Verweisen auf Beziehungen
Bei einigen paketbasierten Formaten können URI-Verweise im Inhalt vermieden werden und Verweise auf Beziehungen delegiert werden. Diese Delegierungstechnik basiert auf der Verwendung eindeutiger ID-Werte für jedes Relationship-Element , um relative Verweise im Teilinhalt den entsprechenden Beziehungen zuzuordnen.
Beispiel: Zuordnen relativer Verweise im Teilinhalt zu Beziehungen
Ein Paket, das sich in file:///c:/office12/sample.docx befindet, verfügt über einen Teil namens /word/document.xml , der enthält.
<a:blip relEmbed="rId6" relLink="" w="0" h="0"/>.
Der diesem Teil angefügte Beziehungsteil enthält das -Element.
<Beziehungs-ID="rId6"
Type="https://schemas.microsoft.com/office/2006/relationships/image"
TargetMode="Internal" Target="media/image1.jpeg"/>.
Dadurch wird das Element mit dem Teil /word/media/image1.jpeg verknüpft.
Der Vorteil dieses Ansatzes besteht darin, dass eine Anwendung alle Verweise innerhalb eines Pakets identifizieren und verwalten kann, ohne den Inhalt in den Teilen zu betrachten.
Wenn Verweise jedoch auf Beziehungen delegiert werden, funktionieren Paketteile, die in lose Dateien extrahiert werden, möglicherweise nicht ordnungsgemäß. Damit Beziehungsziele nach der Extraktion funktionieren, erfordert eine verbrauchende Anwendung spezielle Kenntnisse über Beziehungen, Open Packaging Conventions für die Benennung von Beziehungsteilen und die Definition von Basis-URIs für Beziehungsdateien.
Programmierunterstützung für "pack:"-URIs
Anwendungen, die Pakete erstellen und/oder nutzen, funktionieren mit Paket- und Teiladressen und lösen relative Verweise innerhalb des Inhalts von Teilen auf. .NET Framework 3.0, das die von Microsoft bereitgestellten verwalteten APIs der nächsten Generation bereitstellt, enthält Klassen, die das Adressierungsmodell der Open Packaging Conventions unterstützen. Diese Klassen ermöglichen es Anwendungen, Verweise zu erstellen und zu analysieren und Paketressourcen abzurufen. Die PackUriHelper-Klasse wird verwendet, um die Behandlung von "pack:"-URIs zu erleichtern. Die PackWebRequest-Klasse wird verwendet, um Ressourcen abzurufen, die mithilfe von "pack:"-URIs adressiert werden.
In diesem Abschnitt werden die Funktionen veranschaulicht, die diese Dienste beim Erstellen, Analysieren und Auflösen von Verweisen ausführen.
Bereitstellen der Paketdienste
Die .NET Framework Version 3.0 (oder höher) muss installiert sein, um die Verpackungsdienstklassen verwenden zu können. Die Klassen finden Sie im System.IO.Packaging-Namespace .
Bevor Sie System.Uri für Vorgänge verwenden, bei denen "pack:"-URIs beteiligt sind, muss das URI-Schema "pack:" für die Anwendungsdomäne registriert werden. Die einfachste Möglichkeit, das URI-Schema "pack:" zu registrieren, ist das Aufrufen einer beliebigen Methode der PackUriHelper-Klasse . Das Schema kann auch registriert werden, ohne die Hilfsklasse mit der UriParser.Register-Methode aufzurufen, wie im folgenden Beispiel gezeigt. Die Verwendung dieser Methode erfordert jedoch Sicherheitsberechtigungen.
Beispiel: Registrieren des URI-Schemas "pack:"
//To register the "pack:" URI scheme without calling PackUriHelper
UriParser.Register(new GenericUriParser
(GenericUriParserOptions.GenericAuthority),
"pack", -1);
Abrufen des "pack:"-URI einer Zielressource
Beim Verbrauch eines Pakets kann das gesamte Paket oder ein Teil gleichzeitig als Objekt abgerufen werden. In beiden Fällen kann die PackUriHelper.Create-Methode verwendet werden, um den URI "pack:" der Paket- oder Teilressource zu erstellen. Dieser "pack:"-URI wird dann an die PackWebRequest-Methode übergeben, um die Ressource abzurufen. PackWebRequest wird im nächsten Abschnitt "Abrufen von Paketressourcen mithilfe von PackWebRequest" ausführlicher erläutert.
Ein häufiges Beispiel dafür, wie die PackUriHelper- und PackWebRequest-Klassen verwendet werden können, um die Verwendung eines Pakets zu unterstützen, finden Sie in den folgenden Schritten. Wenn der Paket-URI und der Teil-URI bekannt sind, kann eine Anwendung Folgendes ausführen:
- Erstellen Sie mithilfe von PackUriHelper einen "pack:"-URI aus dem Paket-URI und dem Teil-URI.
- Rufen Sie einen Datenstrom von Bits ab, indem Sie PackWebRequest aufrufen.
- Laden Sie den Inhalt des Teils und analysieren Sie, um relative Verweise abzurufen.
- Lösen Sie diese relativen Verweise mit dem Teilbasis-URI (der in Schritt 1 zusammengesetzte "pack:"-URI) auf.
- Verwenden Sie System.Uri , um die relativen Verweise aufzulösen, und verwenden Sie PackWebRequest , um die angegebenen Ressourcen abzurufen.
Erstellen eines "pack:"-URI für ein gewünschtes Paket
Der "pack:"-URI des Pakets kann mithilfe der PackUriHelper.Create-Methode 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 an PackWebRequest übergeben, um die Paketressource abzurufen.
Erstellen eines "pack:"-URI für ein gewünschtes Teil
Der "pack:"-URI des Teils kann mithilfe der PackUriHelper.Create-Methode 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 an PackWebRequest übergeben, um die Teileressource abzurufen.
Auflösen relativer Verweise
Beim Verarbeiten des Inhalts eines Teils werden möglicherweise relative Verweise gefunden, die auf andere Teile oder Ressourcen verweisen. Das Auflösen dieser Verweise ist ein erster Schritt beim Abrufen der Ressourcen, auf die verwiesen wird.
Ein relativer Verweis im Inhalt eines Teils wird anhand des Basis-URI eines Teils auf den "pack:"-URI des Zielteils aufgelöst. Der "pack:"-URI des Zielteils wird an PackWebRequest übergeben, um die Teileressource aus dem Paket abzurufen. Der Name eines Zielteils, der vom "pack:"-URI des Zielparts abgeleitet wird, kann auch verwendet werden, um ein Zielteil abzurufen, indem der Teilename an die Package.GetPart-Methode übergeben wird.
Beim Auflösen relativer Verweise auf Zielteile kann die Auflösung mehrere Pfade annehmen, je nachdem, welche Informationen zu Beginn verfügbar sind und ob das Paket geöffnet ist (oder geöffnet werden kann). Zwei dieser Pfade sind wie folgt:
Am Anfang:
- Der "pack:"-URI des Teils, der den Verweis enthält, ist bekannt.
- 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.
Am Anfang:
- Der Name des Teils, der den Verweis enthält, ist bekannt.
- 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 Teilenamen an die Paketklasse
Sobald ein Paket geöffnet ist, ist die Package-Klasse nützlich, um Teile zu Paketen hinzuzufügen, Teile zu erhalten und Teile zu löschen. Methoden der Package-Klasse , z . B. Package.AddPart, Package.DeletePart und Package.GetPart, nehmen einen Part-URI als Parameter an. Die PackUriHelper.CreatePartUri-Methode kann verwendet werden, um einen gültigen Teilenamen aus einem Verweis zu erstellen, der relativ zum Basis-URI des Pakets ist.
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 Generieren relativer Verweise
Eine Erstellungsanwendung muss möglicherweise einen relativen Verweis ableiten, der, wenn er im Inhalt eines Quellteils platziert wird, auf ein Zielteil verweist. Die GetRelativeUri-Methode dient diesem Zweck.
Beispiel: GetRelativeUri-Beispiel
//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 mithilfe von PackWebRequest
Anwendungen können Pakete und Komponentenressourcen mithilfe von PackWebRequest abrufen, einer Klasse, die von System.Net.WebRequest abgeleitet wird. PackWebRequest gibt eine Ressource zurück, die von einem bestimmten "pack:"-URI adressiert wird.
Im Allgemeinen besteht das Initiieren einer PackWebRequest für einen "pack:"-URI aus den folgenden Schritten:
- Die "pack:"-URI-Grammatik wird überprüft.
- Die Autoritätskomponente wird aus dem "pack:"-URI extrahiert und überprüft, ob sie der Grammatik für einen absoluten URI folgt.
- Wenn die Pfadkomponente des "pack:"-URI leer ist:
Der Paketdatenstrom wird für die Autoritätskomponente abgerufen und an den Aufrufer zurückgegeben.
Andernfalls, wenn die Pfadkomponente nicht leer ist:
- Das offene Paket wird für die von der Autoritätskomponente identifizierte Ressource abgerufen. Je nach CachePolicy-Satz ruft PackWebRequest entweder ein geöffnetes Paket aus dem PackageStore ab oder erstellt eine innere WebRequest für die Paketressource und öffnet das Paket aus dem zurückgegebenen Paketstream.
- Der Teil wird mithilfe der Pfadkomponente des "pack:"-URI als Teilename abgerufen.
- Der Teildatenstrom wird abgerufen und an den Aufrufer zurückgegeben.
PackWebResponse.GetStream gibt einen Datenstrom von Bits zurück, der entweder das gesamte Paket (ein Paketstream) oder ein einzelnes Teil eines Pakets (ein Teildatenstrom) darstellt.
Im Gegensatz zu den meisten WebResponse-Streams kann ein Paketstream mithilfe von Stream.Seek gesucht werden. Ein Paketstream kann verwendet werden, um ein Paketobjekt zu erstellen.
Beim Betrieb mit einer Paketressource über ein "http:"-Protokoll unterstützt PackWebRequestdas progressive Laden von Teilen, d. h. die Möglichkeit, Teileressourcen in einer beliebigen Reihenfolge abzurufen, ohne alle Daten im Paket bis zu den Teildaten zu laden.
PackWebRequest stellt nur Funktionen für den Ressourcenverbrauch bereit. Sie kann nicht zum Posten oder Senden von Daten an einen Server verwendet werden.
PackWebRequest unterstützt derzeit weder asynchrone Vorgänge (z. B . BeginGetResponse) noch PackWebRequest geschachtelte Pakete (weiter oben unter Adressierung von Teilen innerhalb eines Pakets beschrieben).
The PackageStore
Beim Laden von Paketen mit Teilen, die zahlreiche Verweise auf andere Teile enthalten, kann die Antwortzeit für Ressourcenanforderungen verbessert und der Netzwerkdatenverkehr mithilfe des PackageStore reduziert werden. PackageStore ist ein anwendungslokales Wörterbuch mit Verweisen auf geöffnete Pakete. Jedes im PackageStore registrierte Paket wird durch einen Schlüssel-URI-Wert identifiziert.
Der PackageStore ermöglicht Es PackWebRequest , Ressourcen nach Bedarf aus einem Paket abzurufen, ohne jedes Mal eine Serveranforderung zu stellen, wenn eine andere Ressource aus diesem Paket benötigt wird.
Der PackageStore wird nicht automatisch durch einen Aufruf von PackWebRequest geändert. Er muss explizit geändert werden. Es gibt zwei öffentliche Methoden zum Hinzufügen oder Entfernen von Verweisen auf geöffnete Pakete im PackageStore: Package.AddPackage und Package.RemovePackage.
Die auf PackWebRequest festgelegte Standardcacherichtlinie (CacheIfAvailable) bewirkt, dass die Klasse versucht, den PackageStore zum Abrufen des Pakets zu verwenden. PackWebRequest kann gezwungen werden, den Inhalt des PackageStore beim Abrufen von Ressourcen zu ignorieren, indem die Cacherichtlinie auf BypassCache festgelegt wird, wie im nächsten Abschnitt "Cacherichtlinien" beschrieben.
Beim Abrufen der Bits eines Pakets oder Teils gemäß der Standardcacherichtlinie überprüft PackWebRequest zuerst den PackageStore , um festzustellen, ob ein Paket mit einem Schlüssel registriert ist, der der Autoritätskomponente des "pack:"-URI entspricht. Wenn der PackageStore nicht das Paket für den Schlüssel enthält, erstellt PackWebRequest eine innere WebRequest , um die Ressource mithilfe der Autoritätskomponente des "pack:"-URI herunterzuladen.
Cacherichtlinien
Cacherichtlinien definieren die Regeln, die verwendet werden, um zu bestimmen, ob eine Ressourcenanforderung ausgefüllt werden kann, indem sie eine zwischengespeicherte Kopie der Ressource verwenden.
Bei Verwendung von PackWebRequest können zwei Ebenen der Cacherichtlinie explizit festgelegt werden. Für die PackWebRequest selbst kann eine Cacherichtlinie festgelegt werden, die die Interaktion mit dem PackageStore steuert. Außerdem kann eine Cacherichtlinie für den von einer inneren WebRequest gesteuerten Cache festgelegt werden. Auf die innere WebRequest kann mithilfe von PackWebRequest.GetInternalRequest()zugegriffen werden.
Die für die innere WebRequest festgelegte Cacherichtlinie hat keine Auswirkung, wenn PackWebRequest.CachePolicy auf CacheOnly festgelegt ist, sodass die Paketressource aus dem PackageStore abgerufen wird.
PackWebRequest.CachePolicy unterstützt aufgrund der spezifischen Funktionen des PackageStore eine Teilmenge von Richtlinien, wie unten aufgeführt.
Tabelle 1. PackWebRequest.CachePolicy-Richtlinien
Cachepolicy | BESCHREIBUNG |
---|---|
BypassCache | Ignorieren Sie PackageStore-Einträge mit einem übereinstimmenden URI. |
CacheOnly | Berücksichtigen Sie nur PackageStore-Einträge (erstellen Sie niemals eine WebRequest , um den Server nach Daten abzufragen). |
CacheIfAvailable | Überprüfen Sie den PackageStore, und verwenden Sie ein beliebiges Paket dort, wenn eines gefunden wird. Stellen Sie andernfalls eine Netzwerkanforderung an die Ressource, die vom Paket-URI (dem inneren URI des "pack:"-URI) angegeben wird. Dies ist die Standardoption. |
Für PackWebRequest führt das Festlegen aller anderen CachePolicy-Werte zu einer WebException.
Progressives Laden
PackWebRequest kann einen Paketteil schrittweise laden, wenn über das Protokoll "http:" auf das Paket zugegriffen wird. Durch das progressive Laden können Anwendungen auf Teilressourcen zugreifen, bevor das gesamte Paket lokal verfügbar ist. Die Funktion des progressiven Ladens von PackWebRequest erfolgt automatisch: Die aufrufende Anwendung verbessert die Leistung, ohne einzugreifen.
Das progressive Laden basiert auf "Bytebereichsanforderungen" für Ressourcen, wie im Protokoll "http:" 1.1 definiert. Das ZIP-Dateiformat, das zum Speichern von Paketen in physischer Form verwendet wird, profitiert von diesem Mechanismus, da das ZIP-Archivformat wichtige Informationen in einem "zentralen Verzeichnis" am physischen Ende der Datei speichert.
Nach dem Anfordern eines gesamten Pakets mithilfe von PackWebRequest beginnt der Dienst mit der Rückgabe eines Datenstroms, für den ein Aufrufer suchen kann. Wenn ein Paket in dem von PackWebRequest bereitgestellten Stream geöffnet wird, kann der Aufrufer Teile schneller abrufen als bei direkten Anforderungen, z. B. mithilfe des "http:"-Protokolls.
Dienste zum Auswerten und Zerlegen von URIs
Identifizieren von Beziehungsteilnamen, die von der Paketklasse zurückgegeben werden
Beim Verwalten einer Auflistung von Teilen, die mit der Package.GetParts-Methode abgerufen wurde, können Beziehungsteile identifiziert werden, sodass sie getrennt von anderen Teilen behandelt werden können. PackUriHelper.IsRelationshipPartUri wird verwendet, um zu identifizieren, ob ein Teil ein Beziehungsteil 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"
Für die Arbeit mit Beziehungsteilnamen stehen zwei weitere PackUriHelper-Methoden zur Verfügung. PackUriHelper.GetRelationshipPartUri gibt einen Beziehungsteilnamen unter Angabe eines Quellteilnamens zurück. PackUriHelper.GetSourcePartUriFromRelationshipPartUri gibt den Namen des Quellteils für einen angegebenen Beziehungsteilnamen zurück.
Vergleich von URIs für Äquivalenz
Eine Anwendung, die beim Erstellen oder Verwenden eines Pakets einen Cache zum Speichern von Teilen verwendet, muss möglicherweise Überprüfungen auf entsprechende Teilenamen durchführen. Die PackUriHelper.ComparePartUri-Methode überprüft die Äquivalenz von Teilenamen.
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"
Verwenden Sie die PackUriHelper.ComparePackUri-Methode , um die lexikalische Äquivalenz von zwei "pack:"-URIs zu bestimmen.
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
Um den Komponentenpaket-URI und den Teil-URI aus einem "pack:"-URI zu extrahieren, verwenden Sie die Methoden PackUriHelper.GetPackageUri bzw . PackUriHelper.GetPartUri.
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-Beispiel
//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"