Model adresowania konwencji otwierania pakietów

 

David Meltzer i Andrey Shur
Microsoft Corporation

Czerwiec 2006 r.

Dotyczy:
   Konwencje otwierania pakietów
   Microsoft Office 2007
   Microsoft Windows Vista
   Microsoft .NET Framework

Krótki opis: Ten artykuł zawiera omówienie modelu adresowania używanego w konwencjach open packaging, w tym o tym, jak są rozwiązywane pakiety i ich części, sposób rozpoznawania odwołań względnych w częściach pakietu oraz sposób, w jaki aplikacje mogą korzystać z modelu adresowania pakietów z pomocą .NET Framework i klas. (16 drukowanych stron)

Zawartość

Wstęp
Model adresowania
Obsługa programowania dla identyfikatorów URI "pack:"
Odwołania

Wstęp

W ramach projektowania pakietu Office 2007 i Windows Vista firma Microsoft wprowadziła konwencje open packaging. Te konwencje opisują sposób organizowania zawartości w "pakiecie". Niektóre przykłady zawartości obejmują dokument, kolekcję multimediów i bibliotekę aplikacji. Pakiety agregują wszystkie składniki zawartości w jeden obiekt.

Aplikacja do przetwarzania wyrazów może używać pakietów, na przykład do przechowywania stron dokumentu, potrzebnych czcionek oraz obrazów, wykresów i adnotacji na stronach. Aplikacja do wyświetlania dokumentów lub zarządzania może wyświetlać tylko części zawartości w pakiecie. Aplikacje mogą używać formatu opartego na pakietach, takiego jak specyfikacja papieru XML (XPS), do wysyłania zawartości i zasobów o stałym układzie do drukarki.

Ten artykuł zawiera omówienie modelu adresowania używanego w konwencjach open packaging, w tym o tym, jak są rozwiązywane pakiety i ich części oraz jak rozwiązywane są względne odwołania w częściach pakietów. W tym artykule omówiono również, w jaki sposób aplikacje mogą korzystać z modelu adresowania pakietów z pomocą klas .NET Framework i .NET Framework 3.0. Ten artykuł jest napisany głównie dla deweloperów aplikacji, które będą obsługiwać, tworzyć lub zużywać pakiety.

Aby uzyskać pełne informacje normatywne potrzebne do zaimplementowania modelu adresowania pakietów, zobacz specyfikację konwencji otwierania pakietów. Zestawy SDK .NET Framework 3.0 i .NET zawierają więcej informacji na temat omówionych klas i metod.

Materiał przedstawiony w tym omówieniu zakłada podstawową wiedzę na temat specyfikacji identyfikatora URI. Następujące terminy są używane zgodnie z RFC 3986: URI, URI reference, scheme component, authority component, path component, path-absolute i względne odwołanie. Termin URI zawsze określa bezwzględną formę identyfikatora URI — składnik schematu jest obecny, a wszystkie inne składniki są zgodne z gramatyką specyficzną dla schematu. Termin adresowalny, jak użyto tutaj, wskazuje, że identyfikator URI istnieje, który identyfikuje zasób.

Model adresowania

Konwencje otwierania pakietów definiują model logiczny do organizowania zawartości i zasobów pakietu oraz zapewniają mapowanie z tego modelu logicznego na fizyczną reprezentację na podstawie pliku ZIP, XML i innych dostępnych technologii.

Model tworzenia pakietów logicznych opisany przez konwencje open packaging definiuje abstrakcję pakietu, która przechowuje kolekcję części. Części mogą mieć relacje ze sobą, a pakiet może mieć relacje z częściami. Model pakowania określa, w jaki sposób części w pakiecie są nazwane, przywołyzowane i powiązane. Model adresowania zdefiniowany przez Konwencje jest podstawą możliwości odwołowania się do zasobów częściowych i uzyskiwania ich w pakiecie.

Adresowalne zasoby pakietu

Wystąpienie pakietu jako całość jest zasobem adresowalnym, podobnie jak każda część przechowywana w wystąpieniu pakietu.

Adresowanie pakietu jako jednostki

Aplikacje mogą używać identyfikatora URI z dowolnym schematem (na przykład "http:", "ftp:" itd.), aby rozwiązać problem z pakietem jako jednostką, uzyskując strumień bitów składających się na cały pakiet.

Aplikacje mogą również adresować pakiet przy użyciu schematu identyfikatora URI "pack:" zdefiniowanego przez Konwencje otwierania pakietów. Ten schemat określa, że kompletny identyfikator URI identyfikujący pakiet jest przechowywany w składniku urzędu identyfikatora URI "pack:" w postaci zakodowanej.

Przykład: adresowanie pakietu

Zasób pakietu jest adresowany przez identyfikatory URI "http:" i "pack:" (odpowiednio) w następujących przykładach:

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

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

Typ MIME uzyskanego zasobu pakietu wskazuje format pliku pakietu — na przykład może to być format dokumentu XPS (xps), Format XML pakietu Office Open (.docx) lub inny format zgodny z konwencjami otwierania pakietów.

Z różnych powodów (takich jak poprawa wydajności) aplikacje mogą używać identyfikatora URI specyficznego dla swojej domeny jako składnika urzędu identyfikatora URI "pack:". Taki identyfikator URI można rozpoznać tylko w kontekście danej aplikacji. Technika programowania używana dla takich identyfikatorów URI specyficznych dla aplikacji jest opisana w dalszej części "PackageStore".

Adresowanie części w pakiecie

Części w pakiecie są rozwiązywane przy użyciu identyfikatorów URI "pack:". Struktura identyfikatora URI "pack:", który adresuje część, jest następująca: ścieżka pack://< authority><>

Przykład: adresowanie części

pack://http%3a,,www.site.com,windows,p1.xps/font/arial.ttf adresuje część o nazwie /font/arial.ttf, w pakiecie adresowanym przez http://www.site.com/windows/p1.xps.

Składnik urzędu przechowuje zakodowany identyfikator URI całego pakietu; składnik path zawiera nazwę części w tym pakiecie. Nazwy części są zgodne z gramatyką zdefiniowaną dla składnika path-absolute URI ([2], sekcja 3.3), z pewnymi dodatkowymi ograniczeniami ([1], sekcja 2.1.1.1).

Przykład: nazwy części

/documents/doc1.xaml

/pages/page4.xaml

/font/arial.ttf

Nazwy części to bez uwzględniania wielkości liter ciągi ASCII. Wszystkie części w pakiecie mają unikatowe nazwy.

Używanie identyfikatorów fragmentów do elementów referencyjnych

Niektóre aplikacje korzystające z konwencji otwierania pakietów mogą odwoływać się do części przy użyciu identyfikatora URI innego niż "pack:" jednostki pakietu z identyfikatorami fragmentów specyficznymi dla formatu.

Przykład: używanie identyfikatora URI innego niż "pakiet", aby odwołać się do części

Identyfikator URI http://www.site.com/windows/p1.xps\#15 służy do odwołowania się do części reprezentującej stronę 15 w dokumencie p1.xps ([3], sekcjach 9.2.2 i 9.2.3).

Chociaż jest to prawidłowe i w niektórych scenariuszach przydatne jest, aby identyfikatory URI inne niż "pack:" odnosiły się do części, takie identyfikatory URI nie mogą być używane jako podstawowe identyfikatory URI do rozpoznawania odwołań względnych w części zawartości.

Odwoływania się do wpisów w częściach

Część jest najbardziej szczegółowym zasobem adresowalnym w pakiecie. Jednak aplikacje mogą wymagać odwoływania się do wpisów w zawartości części. W przypadku niektórych typów zawartości wpisy można odwoływać się za pomocą identyfikatorów fragmentów ([2], sekcja 3.5). Konwencje otwierania pakietów nie określają identyfikatorów fragmentów. Aplikacje korzystające z identyfikatorów fragmentów są odpowiedzialne za prawidłowe przetwarzanie ich.

Przykład: odwoływanie się do wpisów w częściach

pack://http%3a,www.site.com,windows,p1.xps/pages/page1.xaml#//[@Id="A012"] odnosi się do zestawu węzłów XML w zawartości części o nazwie /pages/page1.xaml i o wartości atrybutu IdentyfikatorA012.

Zagnieżdżone pakiety

Pakiety można zagnieżdżać. Część pakietu może przechowywać zawartość dowolnego typu, w tym cały pakiet. Części zagnieżdżonego pakietu można rozwiązać za pomocą identyfikatora URI "pack:" z składnikiem urzędu wskazującym część zawierającą ten zagnieżdżony pakiet ([1], dodatek D.3).

Przykład: adresowanie części w zagnieżdżonych pakietach

Pakiet znajdujący się w lokalizacji http://www.site.com/package zawiera część o nazwie /nested-package

,

adresowany przez pakiet "pack:" URI ://http%3a,www.site.com,package/nested-package.

Część rozwiązana przez powyższy identyfikator URI zawiera jednostkę pakietu zawierającą część o nazwie /p1.xaml.

Adres tej części w zagnieżdżonym pakiecie jest następujący:

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

Odwołania w zawartości części

Części z określonymi typami zawartości, takimi jak XML, mogą zawierać odwołania do identyfikatora URI. Odwołania identyfikatorów URI mogą być identyfikatorami URI lub odwołaniami względnymi. Odwołania identyfikatora URI mogą być reprezentowane w zawartości przez ciągi Unicode. Aplikacje rozpoznające takie odwołania identyfikatora URI muszą przekonwertować ciągi na formularz identyfikatora URI ([4], sekcja 3.1).

Odwołanie względne to identyfikator URI wyrażony względem podstawowego identyfikatora URI zawartości zawierającej odwołanie. Domyślny podstawowy identyfikator URI zawartości części to "pack:" identyfikator URI adresowania części.

Przykład: podstawowy identyfikator URI

Podstawowy identyfikator URI części o nazwie /pages/page1.xaml w pakiecie adresowanym przez http://www.site.com/windows/p1.xps jest następujący:

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

Jeśli potrzebny jest alternatywny podstawowy identyfikator URI w celu rozpoznania odwołań względnych w wpisach zawartości częściowej, aplikacja musi jawnie określić alternatywę. Określone typy zawartości uwidaczniają pewne sposoby określania alternatywnego podstawowego identyfikatora URI. Na przykład kod XML używa atrybutu xml:base, kod HTML używa elementu podstawowego<>, a konwencje open packaging używają atrybutu TargetMode dla elementów relacji.

Użycie identyfikatora URI "pack:" części jako podstawowego identyfikatora URI względnego odwołania gwarantuje, że przywołyny zasób będzie częścią tego samego pakietu ([2], sekcja 5.2), chyba że względne odwołanie znajduje się w rzadko używanym formularzu ścieżki sieciowej (czyli względnym odwołaniem rozpoczynającym się od "//").

Przykład: rozpoznawanie odwołania względnego

Odwołanie względne . /.. /page2.xaml w ramach części adresowanej jako pack://http%3a,www.site.com,windows,p1.xps/pages/page1.xaml jest rozpoznawany jako pack://http%3a,www.site.com,windows,p1.xps/page2.xaml, zwracając się do części o nazwie /page2.xaml.

Producenci pakietów mogą używać nazw części jako prawidłowej formy odwołań względnych. Jednak w przypadku używania nazw części jako odwołań względnych producenci powinni rozważyć, czy odwołania do części można również rozwiązać jako wyodrębnione zasoby poza pakietem. Po wyodrębnieniu części z pakietu nazwy części używane jako odwołania względne mogą nie być rozpoznawane zgodnie z oczekiwaniami. Obowiązkowy wiodący ukośnik dla nazw części, określony przez gramatykę nazwy części, oznacza, że takie odwołania względne są rozpoznawane z katalogu głównego bieżącego urzędu.

Przykład: adresowanie wyodrębnionych zasobów

W zawartości części o nazwie /doc1/pages/page1.xaml względne odwołanie /page2.xaml adresuje część o nazwie /page2.xaml i względne odwołanie ./page3.xaml adresuje część o nazwie /doc1/pages/page3.xaml.

Po częściach /doc1/pages/page1.xaml, /doc1/pages/page3.xaml i /part2.xaml są wyodrębniane z pakietu do plików o nazwie file:///c:/mydocs/doc1/pages/page1.xaml, file:///c:/mydocs/doc1/pages/page3.xaml i file:///c:/mydocs/page2.xaml (odpowiednio), względne odwołanie ./page3.xaml adresuje plik file:///c:/mydocs/doc1/pages/page3.xaml, który jest oczekiwany; jednak względne odwołanie /page2.xaml teraz adresuje plik o nazwie file:///page2.xaml.

Odwołania względne w relacjach

Konwencje otwierania pakietów definiują połączenia między częściami źródłowymi i docelowymi w pakiecie jako relacjami ([1], sekcja 1.3).

Relacje są grupowane i przechowywane na podstawie ich źródeł. Część relacji zawiera relacje pochodzące z tej samej części źródłowej. Każda relacja jest opisywana przez element XML w ramach tej części relacji. Część relacji jest unikatowo skojarzona z tą częścią źródłową (i odwrotnie) przy użyciu zdefiniowanej konwencji nazewnictwa dla części relacji.

Domyślny podstawowy identyfikator URI identyfikatorów URI określonych w każdym elemecie Relacja to "pack:" identyfikator URI części źródłowej ([1], sekcja 1.3.5). Atrybut TargetMode elementu Relacja wskazuje podstawowy identyfikator URI określonej relacji.

Przykład: element relacji

Element w części relacje definiujący relację z części źródłowej o nazwie /pages/page1.xaml do części docelowej /fonts/arial.ttf w tym samym pakiecie może wyglądać następująco:

<Typ relacji="https://schemas.microsoft.com/xps/2005/06/restricted-font"

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

Wartość wewnętrzna atrybutu TargetMode wskazuje, że podstawowy identyfikator URI elementu Relacji jest domyślny dla zawartości części relacji — i taki sam jak identyfikator URI "pack:" części źródłowej relacji. W poprzednim przykładzie podstawowy identyfikator URI elementu Relacji to identyfikator URI "pack:" części /pages/page1.xaml .

Relacje mogą również kierować zasoby zewnętrzne względem lokalizacji całego pakietu.

Przykład: relacja z obiektem docelowym zewnętrznym

W przypadku pakietu znajdującego się w file:///c:/office12/sample.docxelement XML

<Identyfikator relacji="rId9"

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

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

definiuje relację przeznaczoną dla pliku file:///c:/office12/icon.jpg.

Wartość zewnętrzna atrybutu TargetMode określa, że relacja musi być skierowana do zasobu spoza pakietu. Jeśli atrybut Target zawiera względne odwołanie, wymagany jest podstawowy identyfikator URI. Podstawowy identyfikator URI dla tego elementu relacji musi być identyfikatorem URI całego pakietu.

Delegowanie odwołań do relacji

Niektóre formaty oparte na pakietach mogą unikać używania odwołań identyfikatora URI w zawartości, delegowania odwołań do relacji. Ta technika delegowania opiera się na korzystaniu z unikatowych wartości identyfikatorów w każdym elemencie Relacja w celu mapowania odwołań względnych w części do odpowiednich relacji.

Przykład: mapowanie odwołań względnych w części zawartości na relacje

Pakiet znajdujący się w file:///c:/office12/sample.docx ma część o nazwie /word/document.xml , która zawiera

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

Część relacji dołączona do tej części zawiera element

<Identyfikator relacji="rId6"

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

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

Spowoduje to połączenie elementu ze częścią o nazwie /word/media/image1.jpeg.

Zaletą tego podejścia jest to, że aplikacja może identyfikować i obsługiwać wszystkie odwołania w pakiecie bez przeglądania zawartości w częściach.

Jeśli jednak odwołania są delegowane do relacji, części pakietu wyodrębnione do luźnych plików mogą nie działać prawidłowo. Aby cele relacji działały po wyodrębnieniu, aplikacja korzystająca będzie wymagać specjalnej wiedzy na temat relacji, konwencji open packaging na potrzeby nazewnictwa części relacji oraz definicji podstawowych identyfikatorów URI dla plików relacji.

Obsługa programowania dla identyfikatorów URI "pack:"

Aplikacje produkujące i/lub zużywające pakiety będą działać z pakietami i adresami części oraz rozpoznawać względne odwołania w ramach zawartości części. .NET Framework 3.0, który dostarcza zestaw zarządzanych przez firmę Microsoft interfejsów API nowej generacji, obejmuje klasy obsługujące model adresowania konwencji open packaging. Te klasy umożliwiają aplikacjom tworzenie i analizowanie odwołań oraz uzyskiwanie zasobów pakietu. Klasa PackUriHelper służy do ułatwienia obsługi identyfikatorów URI "pack:". Klasa PackWebRequest służy do uzyskiwania zasobów rozwiązanych przy użyciu identyfikatorów URI "pack:".

W tej sekcji przedstawiono funkcje, które te usługi wykonują w komponowaniu, analizowaniu i rozpoznawaniu odwołań.

Udostępnianie usług pakietu

Aby można było używać klas usług pakowania, należy zainstalować .NET Framework w wersji 3.0 (lub nowszej). Klasy można znaleźć w przestrzeni nazw System.IO.Packaging .

Przed użyciem identyfikatora System.Uri dla operacji, w których są zaangażowane identyfikatory URI "pack:", schemat identyfikatora URI "pack:" musi być zarejestrowany dla domeny aplikacji. Najprostszym sposobem zarejestrowania schematu identyfikatora URI "pack:" jest wywołanie dowolnej metody klasy PackUriHelper . Schemat można również zarejestrować bez wywoływania klasy pomocnika przy użyciu metody UriParser.Register , jak pokazano w poniższym przykładzie. Jednak użycie tej metody wymaga uprawnień zabezpieczeń.

Przykład: rejestrowanie schematu identyfikatora URI "pack:"

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

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

Uzyskiwanie identyfikatora URI "pack:" zasobu docelowego

Podczas korzystania z pakietu cały pakiet lub jedna część w danym momencie można uzyskać jako obiekt. W obu przypadkach można użyć metody PackUriHelper.Create do utworzenia identyfikatora URI "pack:" pakietu lub zasobu części. Ten identyfikator URI "pack:" jest następnie przekazywany do metody PackWebRequest w celu uzyskania zasobu. PakietWebRequest został omówiony bardziej szczegółowo w następnej sekcji "Uzyskiwanie zasobów pakietu przy użyciu pakietu PackWebRequest".

Typowym przykładem sposobu użycia klas PackUriHelper i PackWebRequest można użyć do obsługi użycia pakietu, jest szczegółowo opisany w poniższych krokach. Jeśli znany jest identyfikator URI pakietu i identyfikator URI części, aplikacja może:

  1. Utwórz identyfikator URI "pack:" z identyfikatora URI pakietu i identyfikatora URI części przy użyciu elementu PackUriHelper.
  2. Pobierz strumień bitów, wywołując funkcję PackWebRequest.
  3. Załaduj zawartość części i przeanalizuj, aby uzyskać względne odwołania.
  4. Rozwiąż te względne odwołania względem identyfikatora URI podstawowego części (identyfikator URI "pack:" złożony w kroku 1).
  5. Użyj identyfikatora System.Uri , aby rozpoznać odwołania względne i użyć polecenia PackWebRequest , aby uzyskać wskazane zasoby.

Tworzenie identyfikatora URI "pack:" dla żądanego pakietu

Identyfikator URI "pack:" pakietu można utworzyć przy użyciu metody PackUriHelper.Create .

Przykład: 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/"

Utworzony identyfikator URI "pack:" jest przekazywany do elementu PackWebRequest w celu uzyskania zasobu pakietu.

Tworzenie identyfikatora URI "pack:" dla żądanej części

Identyfikator URI "pack:" części można utworzyć przy użyciu metody PackUriHelper.Create .

Przykład: 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"

Utworzony identyfikator URI "pack:" jest przekazywany do elementu PackWebRequest w celu uzyskania zasobu części.

Rozwiązywanie odwołań względnych

Podczas przetwarzania zawartości części odwołania względne można znaleźć, które odwołują się do innych części lub zasobów. Rozwiązywanie tych odwołań jest pierwszym krokiem w uzyskaniu odwołanych zasobów.

Względne odwołanie w zawartości części jest rozpoznawane względem podstawowego identyfikatora URI części do identyfikatora URI "pack:" części docelowej. Identyfikator URI "pack:" części docelowej jest przekazywany do elementu PackWebRequest w celu uzyskania zasobu części z pakietu. Nazwa części docelowej pochodzącej z identyfikatora URI "pack:" części docelowej może również służyć do uzyskania części docelowej, przekazując nazwę części części docelowej do metody Package.GetPart .

Podczas rozpoznawania odwołań względnych do części docelowych istnieje kilka ścieżek, które można podjąć w zależności od tego, jakie informacje są dostępne na początku i czy pakiet jest otwarty (lub może być otwarty). Dwie z tych ścieżek są następujące:

  • Na początku:

    1. Znany jest identyfikator URI "pack:" części zawierającej odwołanie.
    2. Pakiet nie jest otwarty.
    //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.
    
  • Na początku:

    1. Znana jest nazwa części zawierającej odwołanie.
    2. Pakiet jest otwarty.
    //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);
    

Podawanie nazw części do klasy pakietu

Po otwarciu pakietu klasa Package jest przydatna do dodawania części do pakietów, pobierania części i usuwania części. Metody klasy Package , takie jak Package.AddPart, Package.DeletePart i Package.GetPart, biorą udział w identyfikatorze URI jako parametr. Metoda PackUriHelper.CreatePartUri może służyć do utworzenia prawidłowej nazwy części z odwołania względem podstawowego identyfikatora URI pakietu.

Przykład: 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"

Usługa generowania odwołań względnych

Aplikacja tworząca może wymagać uzyskania względnego odwołania, które po umieszczeniu w zawartości części źródłowej wskazuje część docelową. Metoda GetRelativeUri służy do tego celu.

Przykład: GetRelativeUri — przykład

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

Uzyskiwanie zasobów pakietu przy użyciu elementu PackWebRequest

Aplikacje mogą uzyskiwać pakiety i części zasobów przy użyciu funkcji PackWebRequest, klasy pochodzącej z elementu System.Net.WebRequest. Funkcja PackWebRequest zwraca zasób adresowany przez dany identyfikator URI "pack:".

Ogólnie rzecz biorąc, inicjowanie elementu PackWebRequest dla identyfikatora URI "pack:" składa się z następujących kroków:

  1. Sprawdzana jest gramatyka identyfikatora URI "pack:".
  2. Składnik urzędu jest wyodrębniany z identyfikatora URI "pack:" i sprawdzany, czy jest zgodny z gramatyką dla bezwzględnego identyfikatora URI.
  3. Jeśli składnik ścieżki identyfikatora URI "pack:" jest pusty:
  • Strumień pakietu jest uzyskiwany dla składnika urzędu i zwracany do elementu wywołującego.

    W przeciwnym razie, jeśli składnik ścieżki nie jest pusty:

    1. Otwarty pakiet jest uzyskiwany dla zasobu określonego przez składnik urzędu. W zależności od zestawu CachePolicypakiet PackWebRequest uzyskuje otwarty pakiet z magazynu pakietów lub tworzy wewnętrzny element WebRequest dla zasobu pakietu i otwiera pakiet ze strumienia pakietu zwróconego.
    2. Część jest uzyskiwana przy użyciu składnika path identyfikatora URI "pack:" jako nazwy części.
    3. Strumień części jest uzyskiwany i zwracany do elementu wywołującego.

PackWebResponse.GetStream zwraca strumień bitów reprezentujący cały pakiet ( strumień pakietów) lub pojedynczą część pakietu ( strumień częściowy).

W przeciwieństwie do większości strumieni WebResponse strumień pakietu można wyszukiwać przy użyciu funkcji Stream.Seek. Strumień pakietu może służyć do tworzenia obiektu pakietu.

Podczas pracy z zasobem pakietu za pośrednictwem protokołu "http:" pakiet PackWebRequest obsługuje progresywne ładowanie części: czyli możliwość uzyskiwania zasobów części w dowolnej kolejności bez ładowania wszystkich danych w pakiecie aż do części danych.

PakietWebRequest udostępnia tylko obiekty do użycia zasobów. Nie można jej używać do publikowania ani wysyłania danych do serwera.

Funkcja PackWebRequest obecnie nie obsługuje operacji asynchronicznych (takich jak BeginGetResponse) ani pakietów PackWebRequest obsługuje zagnieżdżone pakiety (opisane wcześniej w temacie "Adresowanie części w pakiecie").

Magazyn pakietów

Podczas ładowania pakietów zawierających wiele odwołań do innych części można poprawić czas odpowiedzi dla żądań zasobów, a ruch sieciowy można zmniejszyć przy użyciu magazynu pakietów. PackageStore to lokalny słownik odwołań do otwierania pakietów. Każdy pakiet zarejestrowany w magazynie pakietów jest identyfikowany przez wartość identyfikatora URI klucza.

Pakiet PackageStore umożliwia pakietowi PackWebRequest uzyskiwanie zasobów zgodnie z potrzebami z pakietu bez żądania serwera za każdym razem, gdy jest potrzebny inny zasób z tego pakietu.

Magazyn pakietów nie jest automatycznie zmieniany w wyniku wywołania elementu PackWebRequest — musi zostać jawnie zmodyfikowany. Istnieją dwie metody publiczne używane do dodawania lub usuwania odwołań do otwierania pakietów w magazynie pakietów: Package.AddPackage i Package.RemovePackage.

Domyślne zasady pamięci podręcznej (CacheIfAvailable) ustawione w pakiecie PackWebRequest powodują, że klasa próbuje użyć magazynu pakietów w celu uzyskania pakietu. Funkcja PackWebRequest może być zmuszona zignorować zawartość magazynu pakietów podczas uzyskiwania zasobów, ustawiając zasady pamięci podręcznej na Wartość BypassCache, zgodnie z opisem w następnej sekcji "Zasady pamięci podręcznej".

Podczas uzyskiwania bitów pakietu lub części zgodnie z domyślnymi zasadami pamięci podręcznej funkcja PackWebRequest najpierw sprawdza magazyn pakietów , aby sprawdzić, czy istnieje pakiet zarejestrowany przy użyciu klucza, który jest równy składnikowi urzędu identyfikatora URI "pack:". Jeśli pakiet PackageStore nie zawiera pakietu klucza, funkcja PackWebRequest utworzy wewnętrzny element WebRequest , aby pobrać zasób przy użyciu składnika urzędu identyfikatora URI "pack:".

Zasady pamięci podręcznej

Zasady pamięci podręcznej definiują reguły używane do określania, czy żądanie zasobu można wypełnić przy użyciu buforowanej kopii zasobu.

W przypadku korzystania z funkcji PackWebRequest istnieją dwa poziomy zasad pamięci podręcznej, które można jawnie ustawić. Zasady pamięci podręcznej można ustawić dla samego pakietu PackWebRequest , kontrolując interakcję z magazynem pakietów. Zasady pamięci podręcznej można również ustawić dla pamięci podręcznej kontrolowanej przez wewnętrzny element WebRequest. Dostęp do wewnętrznego elementu WebRequest można uzyskać za pomocą elementu PackWebRequest, używając polecenia PackWebRequest.GetInternalRequest().

Zasady pamięci podręcznej ustawione w wewnętrznym elemecie WebRequest nie będą miały wpływu, jeśli właściwość PackWebRequest.CachePolicy jest ustawiona na Wartość CacheOnly, co powoduje uzyskanie zasobu pakietu z magazynu pakietów.

PackWebRequest.CachePolicy obsługuje podzestaw zasad, jak pokazano poniżej, ze względu na określone możliwości magazynu pakietów.

Tabela 1. PackWebRequest.CachePolicy policies (Zasady packWebRequest.CachePolicy)

CachePolicy Opis
Obejście usługi BypassCache Ignoruj wpisy PackageStore z pasującym identyfikatorem URI.
CacheOnly Należy wziąć pod uwagę tylko wpisy magazynu pakietów (nigdy nie należy tworzyć elementu WebRequest w celu wykonywania zapytań dotyczących serwera dla danych).
CacheIfAvailable Sprawdź magazyn pakietów i użyj dowolnego pakietu, jeśli zostanie znaleziony; w przeciwnym razie należy wysłać żądanie sieciowe do zasobu wskazanego przez identyfikator URI pakietu (wewnętrzny identyfikator URI "pack:". Jest to opcja domyślna.

W polu PackWebRequest ustawienie wszystkich innych wartości CachePolicy powoduje, że element WebException.

Ładowanie progresywne

PakietWebRequest może stopniowo ładować część pakietu, gdy dostęp do pakietu jest uzyskiwany za pośrednictwem protokołu "http:". Postępowe ładowanie umożliwia aplikacjom dostęp do częściowych zasobów, zanim cały pakiet będzie dostępny lokalnie. Funkcja progresywnego ładowania pakietu PackWebRequest jest automatyczna: aplikacja wywołująca zapewnia lepszą wydajność bez interweniowania.

Ładowanie postępowe opiera się na tworzeniu "żądań zakresu bajtów" dla zasobów, zgodnie z definicją w protokole "http:" 1.1. Format pliku ZIP, używany do przechowywania pakietów w formie fizycznej, korzysta z tego mechanizmu, ponieważ format archiwum ZIP przechowuje ważne informacje w "katalogu centralnym" na fizycznym końcu pliku.

Po zażądaniu całego pakietu przy użyciu funkcji PackWebRequest usługa rozpoczyna zwracanie strumienia, na którym obiekt wywołujący może szukać. Gdy pakiet jest otwierany w strumieniu dostarczonym przez pakiet PackWebRequest, obiekt wywołujący może uzyskać części szybciej niż podczas wysyłania żądań bezpośrednich przy użyciu, na przykład protokołu "http:".

Usługi oceny i dekompozycji identyfikatorów URI

Identyfikowanie nazw części relacji zwracanych przez klasę pakietu

Podczas zarządzania kolekcją części uzyskanych przy użyciu metody Package.GetParts można zidentyfikować części relacji, aby mogły być obsługiwane oddzielnie od innych części. Identyfikator PackUriHelper.IsRelationshipPartUri służy do identyfikowania, czy część jest częścią relacji.

Przykład: 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"

Dwie inne metody PackUriHelper są dostępne do pracy z nazwami części relacji. Parametr PackUriHelper.GetRelationshipPartUri zwraca nazwę części relacji przy użyciu nazwy części źródłowej. Parametr PackUriHelper.GetSourcePartUriFromRelationshipPartUri zwraca nazwę części źródłowej dla danej nazwy części relacji.

Porównywanie identyfikatorów URI dla równoważności

Aplikacja, która używa pamięci podręcznej do przechowywania części podczas tworzenia lub używania pakietu, może wymagać sprawdzenia równoważnych nazw części. Metoda PackUriHelper.ComparePartUri sprawdza równoważność nazw części.

Przykład: 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"

Aby określić równoważność leksykalną dwóch identyfikatorów URI "pack:", użyj metody PackUriHelper.ComparePackUri .

Przykład: 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"

Wyodrębnianie identyfikatorów URI składników z identyfikatora URI "pack:"

Aby wyodrębnić identyfikator URI pakietu składnika i identyfikator URI części z identyfikatora URI "pack:", użyj odpowiednio metod PackUriHelper.GetPackageUri i PackUriHelper.GetPartUri.

Przykład: 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"

Przykład: Przykład 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"

Odwołania

Konwencje otwierania pakietów

Jednolity identyfikator zasobu (URI): składnia ogólna

Specyfikacja open XML Paper

Identyfikatory zasobów międzynarodowych (IRI)