Share via


Modelo de direccionamiento de las convenciones de empaquetado abierto

 

David Meltzer y Andrey Shur
Microsoft Corporation

Junio de 2006

Se aplica a:
   Open Packaging Conventions
   Microsoft Office 2007
   Microsoft Windows Vista
   Microsoft .NET Framework

Resumen: En este artículo se proporciona información general sobre el modelo de direccionamiento que se usa en las convenciones de empaquetado abierto, incluido cómo se abordan los paquetes y sus partes, cómo se resuelven las referencias relativas en los elementos del paquete y cómo las aplicaciones pueden usar el modelo de direccionamiento de paquetes con la ayuda de .NET Framework y las clases. (16 páginas impresas)

Contenido

Prefacio
Modelo de direccionamiento
Compatibilidad de programación con URI "pack:"
Referencias

Prefacio

Como parte del diseño de Office 2007 y Windows Vista, Microsoft introdujo las convenciones de empaquetado abierto. Estas convenciones describen cómo se puede organizar el contenido en un "paquete". Algunos ejemplos de contenido incluyen un documento, una colección de medios y una biblioteca de aplicaciones. Los paquetes agregan todos los componentes del contenido en un solo objeto.

Una aplicación de procesamiento de texto puede usar paquetes, por ejemplo, para almacenar las páginas de un documento, las fuentes necesarias y las imágenes, gráficos y anotaciones en las páginas. Una aplicación de visualización o administración de documentos solo puede mostrar partes del contenido de un paquete. Las aplicaciones pueden usar un formato basado en paquetes, como la Especificación de papel XML (XPS), para enviar contenido y recursos de diseño fijo a una impresora.

En este artículo se proporciona información general sobre el modelo de direccionamiento que se usa en las convenciones de empaquetado abierto, incluido cómo se abordan los paquetes y sus partes, y cómo se resuelven las referencias relativas en los elementos del paquete. En este artículo también se describe cómo las aplicaciones pueden usar el modelo de direccionamiento de paquetes con la ayuda de las clases .NET Framework y .NET Framework 3.0. Este artículo se escribe principalmente para desarrolladores de aplicaciones que controlarán, generarán o consumirán paquetes.

Para obtener información normativa completa necesaria para implementar el modelo de direccionamiento de paquetes, consulte la especificación para las convenciones de empaquetado abierto. Los SDK de .NET Framework 3.0 y .NET proporcionan más información sobre las clases y los métodos descritos.

El material presentado en esta introducción supone un conocimiento básico de la especificación de URI. Los términos siguientes se usan según RFC 3986: URI, referencia de URI, componente de esquema, componente de autoridad, componente de ruta de acceso, ruta de acceso absoluta y referencia relativa. El término URI siempre denota la forma absoluta de un URI: el componente de esquema está presente y todos los demás componentes coinciden con la gramática específica del esquema. El término direccionable, como se usa aquí, indica que existe un URI que identifica un recurso.

Modelo de direccionamiento

Las convenciones de empaquetado abierto definen un modelo lógico para organizar el contenido y los recursos de un paquete, y proporcionan una asignación de este modelo lógico a una representación física, basada en ZIP, XML y otras tecnologías abiertamente disponibles.

El modelo de empaquetado lógico descrito por las convenciones de empaquetado abierto define una abstracción de paquete que contiene una colección de partes. Los elementos pueden tener relaciones entre sí y el paquete puede tener relaciones con partes. El modelo de empaquetado especifica cómo se denominan, hacen referencia a los elementos de un paquete y se relacionan. El modelo de direccionamiento definido por las convenciones es la base para poder hacer referencia y obtener recursos de elementos en un paquete.

Recursos de paquetes direccionables

Una instancia de paquete en su conjunto es un recurso direccionable, como cada parte de la instancia del paquete.

Direccionamiento de un paquete como unidad

Las aplicaciones pueden usar un URI con cualquier esquema (por ejemplo, "http:", "ftp:", etc.) para abordar un paquete como una unidad y adquirir la secuencia de bits que comprende todo el paquete.

Las aplicaciones también pueden abordar un paquete mediante el esquema de URI "pack:" definido por las convenciones de empaquetado abierto. Este esquema especifica que el URI completo que identifica el paquete se mantiene en el componente de autoridad de un URI "pack:" en un formulario codificado.

Ejemplo: Direccionamiento de un paquete

El recurso de paquete se aborda mediante URI "http:" y "pack:" (respectivamente) en los ejemplos siguientes:

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

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

El tipo MIME del recurso de paquete adquirido indica el formato de archivo del paquete; por ejemplo, puede ser formato de documento XPS (.xps), formato Office Open XML (.docx) o algún otro formato que se ajuste a las convenciones de empaquetado abierto.

Por varias razones (como mejorar el rendimiento), las aplicaciones pueden usar un URI específico de su dominio como componente de autoridad de un URI "pack:". Este URI solo se puede resolver en el contexto de una aplicación determinada. La técnica de programación que se usa para estos URI específicos de la aplicación se describe más adelante, en "The PackageStore".

Direccionamiento de elementos dentro de un paquete

Los elementos de un paquete se abordan mediante URI "pack:". La estructura de un URI "pack:" que direcciona una parte es la siguiente: pack://< ruta de acceso de autenticación><>

Ejemplo: Direccionamiento de elementos

pack://http%3a,,www.site.com,windows,p1.xps/fonts/arial.ttf direcciona la parte denominada /fonts/arial.ttf, en el paquete direccionado por http://www.site.com/windows/p1.xps.

El componente de autoridad contiene el URI codificado de todo el paquete; el componente de ruta de acceso contiene el nombre del elemento de ese paquete. Los nombres de elementos se ajustan a la gramática definida para el componente URI absoluto de ruta de acceso ([2], sección 3.3), con algunas restricciones adicionales ([1], sección 2.1.1.1).

Ejemplo: Nombres de elementos

/documents/doc1.xaml

/pages/page4.xaml

/fonts/arial.ttf

Los nombres de los elementos no distinguen mayúsculas de minúsculas cadenas ASCII. Todos los elementos de un paquete tienen nombres únicos.

Uso de identificadores de fragmentos para hacer referencia a elementos

Algunas aplicaciones que usan las convenciones de empaquetado abierto pueden hacer referencia a una parte mediante un URI que no sea "pack:" de una unidad de paquete con identificadores de fragmentos específicos del formato.

Ejemplo: Usar un URI que no sea "pack:" para hacer referencia a un elemento

El URI http://www.site.com/windows/p1.xps\#15 se usa para hacer referencia a la parte que representa la página 15 del documento p1.xps ([3], secciones 9.2.2 y 9.2.3).

Aunque es válido y, para determinados escenarios, resulta útil que los URI que no sean "pack:" hagan referencia a elementos, estos URI no se pueden usar como URI base para resolver referencias relativas en el contenido del elemento.

Hacer referencia a entradas dentro de partes

Una parte es el recurso direccionable más granular dentro de un paquete. Sin embargo, es posible que las aplicaciones necesiten hacer referencia a entradas dentro del contenido de una parte. Para determinados tipos de contenido, se puede hacer referencia a las entradas mediante identificadores de fragmentos ([2], sección 3.5). Las convenciones de empaquetado abierto no especifican identificadores de fragmento. Las aplicaciones que usan identificadores de fragmento son responsables de procesarlas correctamente.

Ejemplo: hacer referencia a entradas dentro de partes

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml#//[@Id="A012"] hace referencia a un conjunto de nodos XML dentro del contenido del elemento denominado /pages/page1.xaml y tener el valor de atributo Id de A012.

Paquetes anidados

Los paquetes se pueden anidar. Un elemento de un paquete puede contener contenido de cualquier tipo, incluido un paquete completo. Las partes de un paquete anidado se pueden abordar mediante un URI "pack:", con un componente de autoridad que indica la parte que contiene este paquete anidado ([1], Apéndice D.3).

Ejemplo: Direccionamiento de elementos en paquetes anidados

Un paquete ubicado en http://www.site.com/package contiene un elemento denominado /nested-package

,

direccionado por el paquete de URI "pack:" http%3a,,www.site.com,package/nested-package.

El elemento direccionado por el URI anterior contiene una unidad de paquete, que contiene una parte denominada /p1.xaml.

La dirección de esta parte del paquete anidado es la siguiente:

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

Referencias en contenido de elementos

Las partes que tienen ciertos tipos de contenido, como XML, pueden contener referencias de URI. Las referencias de URI pueden ser URI o referencias relativas. Las referencias de URI se pueden representar en el contenido mediante cadenas Unicode. Las aplicaciones que resuelven estas referencias URI deben convertir las cadenas en un formulario URI ([4], sección 3.1).

Una referencia relativa es un URI que se expresa en relación con el URI base del contenido que contiene la referencia. El URI base predeterminado para el contenido del elemento es el URI "pack:" que direcciona el elemento.

Ejemplo: URI base

El URI base de un elemento denominado /pages/page1.xaml en un paquete direccionado por http://www.site.com/windows/p1.xps es el siguiente:

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

Si se necesita un URI base alternativo para resolver las referencias relativas en las entradas del contenido del elemento, una aplicación debe especificar explícitamente la alternativa. Determinados tipos de contenido exponen ciertas formas de especificar el URI base alternativo. Por ejemplo, XML usa el atributo xml:base , HTML usa el <elemento base> y open Packaging Conventions usan el atributo TargetMode para los elementos Relationship .

El uso del URI "pack:" de un elemento como URI base para una referencia relativa garantiza que el recurso al que se hace referencia formará parte del mismo paquete ([2], sección 5.2), a menos que la referencia relativa esté en el formulario de ruta de acceso de red usado rara vez (es decir, una referencia relativa que comience por "//").

Ejemplo: Resolución de una referencia relativa

Referencia relativa .. /.. /page2.xaml dentro de la parte dirigida como pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml se resuelve para empaquetar://http%3a,,www.site.com,windows,p1.xps/page2.xaml, direccionando el elemento denominado /page2.xaml.

Los productores de paquetes pueden usar nombres de pieza como una forma válida de referencias relativas. Sin embargo, al usar nombres de pieza como referencias relativas, los productores deben considerar si las partes a las que se hace referencia también se pueden abordar como recursos extraídos fuera del paquete. Una vez que se han extraído elementos de un paquete, es posible que los nombres de elementos usados como referencias relativas no se resuelvan según lo previsto. La barra diagonal inicial obligatoria para los nombres de pieza, especificados por la gramática de nombre de parte, implica que dichas referencias relativas se resuelven desde la raíz de la autoridad actual.

Ejemplo: Direccionamiento de recursos extraídos

En el contenido de un elemento denominado /doc1/pages/page1.xaml, la referencia relativa /page2.xaml direcciona el elemento denominado /page2.xaml y la referencia relativa ./page3.xaml direcciona el elemento denominado /doc1/pages/page3.xaml.

Después de que los elementos /doc1/pages/page1.xaml, /doc1/pages/page3.xaml y /part2.xaml se extraigan del paquete a los archivos denominados file:///c:/mydocs/doc1/pages/page1.xaml, file:///c:/mydocs/doc1/pages/page3.xaml y file:///c:/mydocs/page2.xaml (respectivamente), la referencia relativa ./page3.xaml se dirige al archivo file:///c:/mydocs/doc1/pages/page3.xaml, que se espera; sin embargo, la referencia relativa /page2.xaml ahora direcciona el archivo denominado file:///page2.xaml.

Referencias relativas en relaciones

Las convenciones de empaquetado abierto definen las conexiones entre las partes de origen y destino de un paquete como relaciones ([1], sección 1.3).

Las relaciones se agrupan y almacenan en función de sus orígenes. Una parte de relaciones contiene relaciones que se originan en la misma parte de origen. Cada relación se describe mediante un elemento XML dentro del contenido de esta parte de relaciones. La parte de relaciones está asociada de forma única a esta parte de origen (y viceversa) mediante una convención de nomenclatura definida para la parte de relaciones.

El URI base predeterminado para los URI especificados en cada elemento Relationship es el URI "pack:" de la parte de origen ([1], sección 1.3.5). El atributo TargetMode de un elemento Relationship indica el URI base de la relación especificada.

Ejemplo: Elemento Relationship

El elemento de la parte de relaciones que define una relación de un elemento de origen denominado /pages/page1.xaml con la parte de destino /fonts/arial.ttf dentro del mismo paquete puede tener un aspecto similar al siguiente:

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

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

El valor Interno del atributo TargetMode indica que el URI base del elemento Relationship es el valor predeterminado para el contenido del elemento de relaciones y el mismo que el URI "pack:" de la parte de origen de relaciones. En el ejemplo anterior, el URI base del elemento Relationship es el URI "pack:" del elemento /pages/page1.xaml .

Las relaciones también pueden tener como destino recursos externos en relación con la ubicación del paquete completo.

Ejemplo: Relación con destino externo

Para un paquete ubicado en file:///c:/office12/sample.docx, el elemento XML

<Relationship Id="rId9"

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

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

define la relación que tiene como destino el archivo file:///c:/office12/icon.jpg.

El valor Externo del atributo TargetMode especifica que la relación debe tener como destino un recurso fuera del paquete. Si el atributo Target contiene una referencia relativa, se requiere un URI base. El URI base de este elemento de relación debe ser el URI del paquete completo.

Delegación de referencias a relaciones

Algunos formatos basados en paquetes pueden evitar el uso de referencias de URI en el contenido y delegar referencias a relaciones. Esta técnica de delegación se basa en el uso de valores id únicos en cada elemento Relationship para asignar referencias relativas en el contenido de la parte a las relaciones correspondientes.

Ejemplo: Asignación de referencias relativas en el contenido de la parte a relaciones

Un paquete ubicado en file:///c:/office12/sample.docx tiene una parte denominada /word/document.xml que contiene

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

La parte de relaciones adjunta a esta parte contiene el elemento

<Relationship Id="rId6"

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

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

Esto vincula el elemento al elemento denominado /word/media/image1.jpeg.

La ventaja de este enfoque es que una aplicación puede identificar y mantener todas las referencias dentro de un paquete, sin examinar el contenido de las partes.

Sin embargo, si las referencias se delegan a relaciones, es posible que los elementos de paquete extraídos en archivos sueltos no funcionen correctamente. Para que los destinos de relación funcionen después de la extracción, una aplicación de consumo requerirá conocimientos especiales sobre las relaciones, las convenciones de empaquetado abierto para asignar nombres a elementos de relación y la definición de URI base para los archivos de relación.

Compatibilidad de programación con URI "pack:"

Las aplicaciones que producen o consumen paquetes funcionarán con direcciones de paquetes y partes y resolverán referencias relativas dentro del contenido de las partes. .NET Framework 3.0, que ofrece el conjunto de API administradas de próxima generación proporcionadas por Microsoft, incluye clases que admiten el modelo de direccionamiento de las convenciones de empaquetado abierto. Estas clases permiten a las aplicaciones crear y analizar referencias y obtener recursos de paquete. La clase PackUriHelper se usa para facilitar el control de los URI "pack:". La clase PackWebRequest se usa para obtener recursos dirigidos mediante URI "pack:".

En esta sección se muestran las funciones que realizan estos servicios en la redacción, el análisis y la resolución de referencias.

Hacer que los servicios de paquete estén disponibles

La versión 3.0 de .NET Framework (o posterior) debe instalarse para poder usar las clases de servicios de empaquetado. Las clases se pueden encontrar en el espacio de nombres System.IO.Packaging .

Antes de usar System.Uri para las operaciones en las que intervienen los URI "pack:", el esquema de URI "pack:" debe estar registrado para el dominio de aplicación. La manera más fácil de registrar el esquema de URI "pack:" es llamando a cualquier método de la clase PackUriHelper . El esquema también se puede registrar, sin llamar a la clase auxiliar, mediante el método UriParser.Register , como se muestra en el ejemplo siguiente. Sin embargo, el uso de este método requiere permisos de seguridad.

Ejemplo: Registro del esquema de URI "pack:"

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

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

Obtención del URI "pack:" de un recurso de destino

Al consumir un paquete, todo el paquete o una parte a la vez, se puede obtener como un objeto . En cualquier caso, el método PackUriHelper.Create se puede usar para crear el URI "pack:" del recurso de paquete o parte. Este URI "pack:" se pasa al método PackWebRequest para obtener el recurso. PackWebRequest se describe con más detalle en la sección siguiente, "Obtener recursos de paquete mediante PackWebRequest".

En los pasos siguientes se detalla un ejemplo común de cómo se pueden usar las clases PackUriHelper y PackWebRequest para admitir el consumo de un paquete. Si se conoce el URI del paquete y el URI de la parte, una aplicación puede:

  1. Cree un URI "pack:" a partir del URI del paquete y del URI de la parte, mediante PackUriHelper.
  2. Obtenga una secuencia de bits mediante una llamada a PackWebRequest.
  3. Cargue el contenido del elemento y analice para obtener referencias relativas.
  4. Resuelva estas referencias relativas en el URI base de la parte (el URI "pack:" compuesto en el paso 1).
  5. Use System.Uri para resolver las referencias relativas y use PackWebRequest para obtener los recursos indicados.

Creación de un URI "pack:" para un paquete deseado

El URI "pack:" del paquete se puede crear mediante el método PackUriHelper.Create .

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

El URI "pack:" creado se pasa a PackWebRequest para obtener el recurso del paquete.

Crear un URI "pack:" para un elemento deseado

El URI "pack:" del elemento se puede crear mediante el método PackUriHelper.Create .

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

El URI "pack:" creado se pasa a PackWebRequest para obtener el recurso de elemento.

Resolución de referencias relativas

Al procesar el contenido de una parte, es posible que se encuentren referencias relativas que hacen referencia a otros elementos o recursos. Resolver estas referencias es un primer paso para obtener los recursos a los que se hace referencia.

Una referencia relativa en el contenido de un elemento se resuelve con el URI base de un elemento en el URI "pack:" de la parte de destino. El URI "pack:" de la parte de destino se pasa a PackWebRequest para obtener el recurso de elemento del paquete. El nombre de una parte de destino, derivada del URI "pack:" de la parte de destino, también se puede usar para obtener una parte de destino, pasando el nombre del elemento al método Package.GetPart .

Al resolver referencias relativas a elementos de destino, hay varias rutas de acceso que la resolución puede tomar, en función de la información disponible al principio y de si el paquete está abierto (o se puede abrir). Dos de estas rutas de acceso son las siguientes:

  • Al principio:

    1. Se conoce el URI "pack:" de la parte que contiene la referencia.
    2. El paquete no está abierto.
    //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.
    
  • Al principio:

    1. Se conoce el nombre de la parte que contiene la referencia.
    2. El paquete está abierto.
    //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);
    

Proporcionar nombres de elementos a la clase package

Una vez abierto un paquete, la clase Package es útil para agregar elementos a paquetes, obtener elementos y eliminar elementos. Los métodos de la clase Package , como Package.AddPart, Package.DeletePart y Package.GetPart, toman un URI de parte como parámetro. El método PackUriHelper.CreatePartUri se puede usar para crear un nombre de elemento válido a partir de una referencia relativa al URI base del paquete.

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

Servicio para generar referencias relativas

Es posible que una aplicación de creación tenga que derivar una referencia relativa que, cuando se coloca en el contenido de una parte de origen, apunta a una parte de destino. El método GetRelativeUri sirve para este propósito.

Ejemplo: Ejemplo de 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"

Obtención de recursos de paquete mediante PackWebRequest

Las aplicaciones pueden obtener paquetes y recursos de elementos mediante PackWebRequest, una clase derivada de System.Net.WebRequest. PackWebRequest devuelve un recurso direccionado por un identificador URI "pack:".

En general, iniciar un PackWebRequest para un URI "pack:" consta de los pasos siguientes:

  1. Se comprueba la gramática de URI "pack:".
  2. El componente de autoridad se extrae del URI "pack:" y se comprueba para ver si sigue la gramática de un URI absoluto.
  3. Si el componente de ruta de acceso del URI "pack:" está vacío:
  • El flujo de paquete se obtiene para el componente de autoridad y se devuelve al autor de la llamada.

    De lo contrario, si el componente de ruta de acceso no está vacío:

    1. El paquete abierto se obtiene para el recurso identificado por el componente de autoridad. Según el conjunto cachePolicy , PackWebRequest obtiene un paquete abierto de PackageStore o crea un WebRequest interno para el recurso del paquete y abre el paquete desde la secuencia de paquetes devuelta.
    2. El elemento se obtiene con el componente de ruta de acceso del URI "pack:" como nombre del elemento.
    3. La secuencia de elementos se obtiene y se devuelve al autor de la llamada.

PackWebResponse.GetStream devuelve una secuencia de bits que representa todo el paquete (una secuencia de paquete) o una sola parte de un paquete (una secuencia de partes).

A diferencia de la mayoría de los flujos de WebResponse, se puede buscar una secuencia de paquete mediante Stream.Seek. Se puede usar una secuencia de paquetes para crear un objeto de paquete.

Cuando se trabaja con el recurso de paquete a través de un protocolo "http:", PackWebRequest admite la carga progresiva de partes: es decir, la capacidad de obtener recursos de elementos en un orden arbitrario, sin cargar todos los datos del paquete hasta los datos del elemento.

PackWebRequest solo proporciona instalaciones para el consumo de recursos. No se puede usar para publicar o enviar datos a un servidor.

PackWebRequest actualmente no admite operaciones asincrónicas (como BeginGetResponse) ni tampoco PackWebRequest admite paquetes anidados (descritos anteriormente, en "Direccionamiento de elementos dentro de un paquete").

The PackageStore

Al cargar paquetes que tienen elementos que contienen numerosas referencias a otras partes, se puede mejorar el tiempo de respuesta de las solicitudes de recursos y se puede reducir el tráfico de red mediante packageStore. PackageStore es un diccionario local de aplicaciones de referencias para abrir paquetes. Cada paquete registrado en packageStore se identifica mediante un valor de URI de clave.

PackageStore permite a PackWebRequest obtener recursos según sea necesario de un paquete, sin realizar una solicitud de servidor cada vez que se necesita otro recurso de ese paquete.

PackageStore no se cambia automáticamente como resultado de una llamada a PackWebRequest; debe modificarse explícitamente. Hay dos métodos públicos que se usan para agregar o quitar referencias para abrir paquetes en PackageStore: Package.AddPackage y Package.RemovePackage.

La directiva de caché predeterminada (CacheIfAvailable) establecida en PackWebRequest hace que la clase intente usar PackageStore para obtener el paquete. PackWebRequest se puede forzar a omitir el contenido de PackageStore al obtener recursos estableciendo la directiva de caché en BypassCache, como se describe en la sección siguiente, "Directivas de caché".

Al obtener los bits de un paquete o parte según la directiva de caché predeterminada, PackWebRequest comprueba primero packageStore para ver si hay un paquete registrado con una clave que sea igual al componente de autoridad del URI "pack:". Si PackageStore no contiene el paquete de la clave, PackWebRequest creará un WebRequest interno para descargar el recurso mediante el componente de autoridad del URI "pack:".

Directivas de caché

Las directivas de caché definen las reglas que se usan para determinar si se puede rellenar una solicitud de recursos mediante una copia almacenada en caché del recurso.

Al usar PackWebRequest, hay dos niveles de directiva de caché que se pueden establecer explícitamente. Se puede establecer una directiva de caché para el propio PackWebRequest , controlando la interacción con packageStore. Además, también se puede establecer una directiva de caché para la caché controlada por un WebRequest interno. PackWebRequest puede acceder a la instancia interna de WebRequest mediante PackWebRequest.GetInternalRequest().

La directiva de caché establecida en el WebRequest interno no tendrá ningún efecto si PackWebRequest.CachePolicy está establecido en CacheOnly, lo que hace que el recurso del paquete se obtenga de PackageStore.

PackWebRequest.CachePolicy admite un subconjunto de directivas, como se muestra a continuación, debido a las funcionalidades específicas de PackageStore.

Tabla 1. Directivas PackWebRequest.CachePolicy

CachePolicy Descripción
BypassCache Omita las entradas packageStore con un URI coincidente.
CacheOnly Considere solo las entradas packageStore (nunca cree un WebRequest para consultar el servidor para obtener datos).
CacheIfAvailable Inspeccione packageStore y use cualquier paquete allí si se encuentra uno; De lo contrario, realice una solicitud de red al recurso indicado por el URI del paquete (el URI interno del URI "pack:"). Este es el valor predeterminado.

Para PackWebRequest, establecer todos los demás valores cachePolicy da como resultado una excepción WebException.

Carga progresiva

PackWebRequest puede cargar progresivamente un elemento de paquete cuando se accede al paquete a través del protocolo "http:". La carga progresiva permite a las aplicaciones acceder a los recursos de elementos antes de que todo el paquete esté disponible localmente. La característica de carga progresiva de PackWebRequest es automática: la aplicación que realiza la llamada experimenta el rendimiento mejorado sin intervención.

La carga progresiva se basa en la realización de "solicitudes de intervalo de bytes" para los recursos, tal como se define en el protocolo "http:" 1.1. El formato de archivo ZIP, que se usa para almacenar paquetes en forma física, se beneficia de este mecanismo, ya que el formato de archivo ZIP mantiene información importante en un "directorio central" al final físico del archivo.

Después de solicitar un paquete completo mediante PackWebRequest, el servicio comienza a devolver una secuencia en la que un autor de la llamada puede buscar. Cuando se abre un paquete en la secuencia proporcionada por PackWebRequest, el autor de la llamada puede obtener elementos más rápidamente que al realizar solicitudes directas mediante, por ejemplo, el protocolo "http:".

Servicios para evaluar y descomponer URI

Identificar nombres de elementos de relación devueltos por la clase package

Al administrar una colección de elementos obtenidos mediante el método Package.GetParts , se pueden identificar partes de relación para que se puedan controlar por separado de otras partes. PackUriHelper.IsRelationshipPartUri se usa para identificar si una parte es una parte de relación.

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

Hay otros dos métodos PackUriHelper disponibles para trabajar con nombres de elementos de relación. PackUriHelper.GetRelationshipPartUri devuelve un nombre de elemento de relación dado un nombre de elemento de origen. PackUriHelper.GetSourcePartUriFromRelationshipPartUri devuelve el nombre del elemento de origen para un nombre de elemento de relación determinado.

Comparación de URI para equivalencia

Es posible que una aplicación que use una memoria caché para almacenar elementos al producir o consumir un paquete necesite realizar comprobaciones de nombres de pieza equivalentes. El método PackUriHelper.ComparePartUri comprueba la equivalencia de los nombres de pieza.

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

Para determinar la equivalencia léxica de dos URI "pack:", use el método PackUriHelper.ComparePackUri .

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

Extracción de URI de componentes de un URI "pack:"

Para extraer el URI del paquete de componentes y el URI de parte de un URI "pack:", use los métodos PackUriHelper.GetPackageUri y PackUriHelper.GetPartUri, respectivamente.

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

Ejemplo: Ejemplo de 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"

Referencias

Open Packaging Conventions

Identificador uniforme de recursos (URI): sintaxis genérica

Open XML Paper Specification

Identificadores de recursos internacionalizados (IRI)