Cómo: Enlazar a datos XML mediante XMLDataProvider y consultas XPath

En este ejemplo se muestra cómo enlazar a datos XML mediante XmlDataProvider.

Con XmlDataProvider, los datos subyacentes a los que se puede acceder mediante el enlace de datos en la aplicación pueden ser cualquier árbol de nodos XML. En otras palabras, XmlDataProvider proporciona una manera cómoda de utilizar cualquier árbol de nodos XML como origen de enlace.

Ejemplo

En el ejemplo siguiente, los datos se insertan directamente como una isla de datos XML dentro de la sección Resources. Una isla de datos XML se debe encapsular entre etiquetas <x:XData> y tener siempre un nodo raíz único, que se corresponde con Inventory en este ejemplo.

Nota

El nodo raíz de los datos XML tiene un atributo xmlns que establece el espacio de nombres de XML en una cadena vacía. Se trata de un requisito para aplicar las consultas XPath a una isla de datos insertada dentro de la página de XML. En este caso de inserción, XAML y, en consecuencia, la isla de datos, hereda el espacio de nombres System.Windows. Por ello, es preciso establecer el espacio de nombres en blanco, a fin de evitar que el espacio de nombres System.Windows certifique las consultas XPath, lo que las dirigiría incorrectamente.

<StackPanel
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Background="Cornsilk">

  <StackPanel.Resources>
    <XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books">
      <x:XData>
        <Inventory xmlns="">
          <Books>
            <Book ISBN="0-7356-0562-9" Stock="in" Number="9">
              <Title>XML in Action</Title>
              <Summary>XML Web Technology</Summary>
            </Book>
            <Book ISBN="0-7356-1370-2" Stock="in" Number="8">
              <Title>Programming Microsoft Windows With C#</Title>
              <Summary>C# Programming using the .NET Framework</Summary>
            </Book>
            <Book ISBN="0-7356-1288-9" Stock="out" Number="7">
              <Title>Inside C#</Title>
              <Summary>C# Language Programming</Summary>
            </Book>
            <Book ISBN="0-7356-1377-X" Stock="in" Number="5">
              <Title>Introducing Microsoft .NET</Title>
              <Summary>Overview of .NET Technology</Summary>
            </Book>
            <Book ISBN="0-7356-1448-2" Stock="out" Number="4">
              <Title>Microsoft C# Language Specifications</Title>
              <Summary>The C# language definition</Summary>
            </Book>
          </Books>
          <CDs>
            <CD Stock="in" Number="3">
              <Title>Classical Collection</Title>
              <Summary>Classical Music</Summary>
            </CD>
            <CD Stock="out" Number="9">
              <Title>Jazz Collection</Title>
              <Summary>Jazz Music</Summary>
            </CD>
          </CDs>
        </Inventory>
      </x:XData>
    </XmlDataProvider>
  </StackPanel.Resources>

  <TextBlock FontSize="18" FontWeight="Bold" Margin="10"
    HorizontalAlignment="Center">XML Data Source Sample</TextBlock>
  <ListBox
    Width="400" Height="300" Background="Honeydew">
    <ListBox.ItemsSource>
      <Binding Source="{StaticResource InventoryData}"
               XPath="*[@Stock='out'] | *[@Number>=8 or @Number=3]"/>
    </ListBox.ItemsSource>

    <!--Alternatively, you can do the following. -->
    <!--<ListBox Width="400" Height="300" Background="Honeydew"
      ItemsSource="{Binding Source={StaticResource InventoryData},
      XPath=*[@Stock\=\'out\'] | *[@Number>\=8 or @Number\=3]}">-->

    <ListBox.ItemTemplate>
      <DataTemplate>
        <TextBlock FontSize="12" Foreground="Red">
          <TextBlock.Text>
            <Binding XPath="Title"/>
          </TextBlock.Text>
        </TextBlock>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</StackPanel>

Como se muestra en este ejemplo, para crear la misma declaración de enlace en la sintaxis de atributo es preciso crear caracteres de escape correctos para los caracteres especiales. Para más información, consulte XML Character Entities and XAML (Entidades de caracteres XML y XAML).

Al ejecutar este ejemplo, ListBox mostrará los elementos siguientes. Se trata de los elementos Title de todos los elementos que se encuentran bajo Books cuyo valor de Stock sea "out" o cuyo valor de Number sea 3 o mayor o igual que 8. Observe que no se devuelve ningún elemento CD porque el valor de XPath establecido en XmlDataProvider indica que solo deben mostrarse los elementos Books (básicamente se establece un filtro).

Captura de pantalla del ejemplo de XPath que muestra el título de cuatro libros.

En este ejemplo, los títulos de libro se muestran porque el XPath del enlace TextBlock de DataTemplate se establece en "Title". Si desea mostrar el valor de un atributo, como el ISBN, deberá establecer ese valor de XPath en "@ISBN".

El método XmlNode.SelectNodes controla las propiedades XPath en WPF. Puede modificar las consultas XPath para obtener resultados distintos. A continuación se muestran algunos ejemplos para la consulta XPath en el ListBox enlazado del ejemplo anterior:

  • XPath="Book[1]" devolverá el primer elemento de libro ("XML in Action"). Tenga en cuenta que los índices de XPath se basan en 1, no en 0.

  • XPath="Book[@*]" devolverá todos los elementos con cualquier atributo.

  • XPath="Book[last()-1]" devolverá los elementos de libro del segundo al último ("Introducing Microsoft .NET").

  • XPath="*[position()>3]" devolverá todos los elementos de libro excepto los 3 primeros.

Al ejecutar una consulta XPath, devuelve un XmlNode o una lista de XmlNodes. XmlNode es un objeto de Common Language Runtime (CLR), lo que significa que puede usar la propiedad Path para enlazar a las propiedades de Common Language Runtime (CLR). Remítase de nuevo al ejemplo anterior. Si el resto del ejemplo permanece igual y cambia el enlace de TextBlock por lo siguiente, verá los nombres de los objetos XmlNodes devueltos en el control ListBox. En este caso, el nombre de todos los nodos devueltos es "Book".

<TextBlock FontSize="12" Foreground="Red">
  <TextBlock.Text>
    <Binding Path="Name"/>
  </TextBlock.Text>
</TextBlock>

En algunas aplicaciones, puede que no sea conveniente insertar XML como una isla de datos dentro del código fuente de la página de XAML, ya que es imprescindible conocer el contenido exacto de los datos en tiempo de compilación. Por lo tanto, también se admite la obtención de los datos de un archivo XML externo, como en el ejemplo siguiente:

<XmlDataProvider x:Key="BookData" Source="data\bookdata.xml" XPath="Books"/>

Si los datos XML residen en un archivo XML remoto, el acceso a ellos se define mediante la asignación de una URL apropiada al atributo Source, como sigue:

<XmlDataProvider x:Key="BookData" Source="http://MyUrl" XPath="Books"/>  

Vea también