2010-04-07 12 views
6

Estoy tratando de usar XPath para seleccionar los elementos que tienen una faceta con valores Location, pero actualmente mis intentos de simplemente seleccionar todos los elementos fallan: el sistema informa felizmente que encontró 0 elementos, luego devoluciones (en su lugar, los nodos se deben procesar mediante un bucle foreach). Agradecería ayuda ya sea para hacer mi consulta original o simplemente para que XPath funcione.C# XPath no encuentra nada

XML

<?xml version="1.0" encoding="UTF-8" ?> 
<Collection Name="My Collection" SchemaVersion="1.0" xmlns="http://schemas.microsoft.com/collection/metadata/2009" xmlns:p="http://schemas.microsoft.com/livelabs/pivot/collection/2009" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<FacetCategories> 
    <FacetCategory Name="Current Address" Type="Location"/> 
    <FacetCategory Name="Previous Addresses" Type="Location" /> 
</FacetCategories> 
    <Items> 
     <Item Id="1" Name="John Doe"> 
      <Facets> 
       <Facet Name="Current Address"> 
        <Location Value="101 America Rd, A Dorm Rm 000, Chapel Hill, NC 27514" /> 
       </Facet> 
       <Facet Name="Previous Addresses"> 
        <Location Value="123 Anywhere Ln, Darien, CT 06820" /> 
        <Location Value="000 Foobar Rd, Cary, NC 27519" /> 
       </Facet> 
      </Facets> 
     </Item> 
    </Items> 
</Collection> 

C#

public void countItems(string fileName) 
{ 
    XmlDocument document = new XmlDocument(); 
    document.Load(fileName); 
    XmlNode root = document.DocumentElement; 
    XmlNodeList xnl = root.SelectNodes("//Item"); 
    Console.WriteLine(String.Format("Found {0} items" , xnl.Count)); 
} 

Hay más en el método que esto, pero ya que esto es todo lo que se ejecute Estoy asumiendo que el problema radica aquí. Llamar al root.ChildNodes devuelve exactamente FacetCategories y Items, por lo que estoy completamente perdido.

Gracias por su ayuda!

Respuesta

17

Su elemento raíz tiene un espacio de nombres. Tendrá que agregar una resolución de espacio de nombres y prefijar los elementos en su consulta.

This article explica la solución. He modificado tu código para que obtenga 1 resultado.

public void countItems(string fileName) 
{ 
    XmlDocument document = new XmlDocument(); 
    document.Load(fileName); 
    XmlNode root = document.DocumentElement; 

    // create ns manager 
    XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(document.NameTable); 
    xmlnsManager.AddNamespace("def", "http://schemas.microsoft.com/collection/metadata/2009"); 

    // use ns manager 
    XmlNodeList xnl = root.SelectNodes("//def:Item", xmlnsManager); 
    Response.Write(String.Format("Found {0} items" , xnl.Count)); 
} 
6

Debido a que tiene un espacio de nombres XML en el nodo raíz, no hay tal cosa como "elemento" en el documento XML, sólo "[espacio de nombres]: El artículo", por lo que la búsqueda de un nodo con XPath, necesita especificar el espacio de nombres.

Si no te gusta, puedes usar la función local-name() para unir todos los elementos cuyo nombre local (la parte del nombre que no sea el prefijo) es el valor que estás buscando. Es una sintaxis un poco fea, pero funciona.

XmlNodeList xnl = root.SelectNodes("//*[local-name()='Item']");