2011-01-18 19 views
6

He aquí un documento XML de ejemplo que coincide con la que yo estoy recibiendo información de:C# XPath ayuda - Expresión no funciona

<?xml version="1.0" standalone="yes"?> 
<Products xmlns="http://tempuri.org/Products.xsd"> 
    <Movies> 
    <Title>Title1</Title> 
    <Language>English</Language> 
    </Movies> 
    <Movies> 
    <Title>Title2</Title> 
    <Language>English</Language> 
    </Movies> 
    <Movies> 
    <Title>Title3</Title> 
    <Language>French</Language> 
    </Movies> 
    <Books> 
    <Title>BTitle1</Title> 
    <Genre>Suspense</Genre> 
    </Books> 
    <Books> 
    <Title>BTitle2</Title> 
    <Genre>Suspense</Genre> 
    </Books> 
    <Books> 
    <Title>BTitle3</Title> 
    <Genre>SciFi</Genre> 
    </Books> 
    <Books> 
    <Title>BTitle4</Title> 
    <Genre>SciFi</Genre> 
    </Books> 
</Products> 

Aquí está mi código para obtener todos los libros con el género de suspenso:

//Get state list using XPath 
XPathDocument xDoc = new XPathDocument(xmlPath); //Path to my file 
XPathNavigator xNav = xDoc.CreateNavigator(); 
string booksQuery = "Books[Genre = \"Suspense\"]"; 
XPathNodeIterator xIter = xNav.Select(booksQuery); 

while (xIter.MoveNext()) 
{ 
    //do stuff with xIter.Current 
} 

He intentado varias consultas incluyendo Products/Books[Genre = \"Suspense\"], Products/Books, ./Books y Books. Mi xter siempre tiene cero elementos.

Soy nuevo en XPath, así que estoy seguro de que es un error muy simple, pero tal vez no. Sé que puedo obtener un DataSet con las tablas [Películas] y [Libros] fuera de este archivo XML usando myDataSet.ReadXml(myXmlPathString); para que el archivo XML no esté dañado. Si eso ayuda a alguno.

Entonces, mi pregunta ... ¿qué estoy haciendo mal?

+0

¿Has probado las comillas simples? es decir, Género = \ 'Suspense \'? – funkymushroom

+0

etiqueta de cierre se cambió el estuche – Rozuur

+0

@Rozuur - Disculpe, error. Arreglado. @funkymushroom - No lo hice. Probaré eso. –

Respuesta

10
XPathDocument xDoc = new XPathDocument(xmlPath); //Path to my file 
XPathNavigator xNav = xDoc.CreateNavigator(); 
XmlNamespaceManager mngr = new XmlNamespaceManager(xNav.NameTable); 
mngr.AddNamespace("p", "http://tempuri.org/Products.xsd"); 
string booksQuery = "//p:Books[p:Genre = \"Suspense\"]"; 
XPathNodeIterator xIter = xNav.Select(booksQuery,mngr); 
+0

Upvoted 'porque llegó allí primero por unos 30 segundos :-( –

+0

@Andy, gracias. Lástima que ninguno de nosotros puede competir con Jon Skeet :) – theChrisKent

+0

me está diciendo; ese hombre es una máquina! –

6

Está buscando un elemento llamado Libros que no está en un espacio de nombres. El elemento Products está configurando el espacio de nombre predeterminado para ese elemento y todos sus descendientes. Tendrá que usar un espacio de nombres en su XPath ... o utilizar un enfoque diferente para realizar consultas, como LINQ a XML. (Personalmente, creemos que LINQ to XML mucho más fácil de tratar que XPath - especialmente cuando se necesita para obtener espacios de nombres involucrados.)

+0

¿cómo podemos usar el resolvedor de espacios de nombres con XPath? Gracias. – Rozuur

+0

Desafortunadamente estoy obligado a .NET 2.0 en este proyecto. ¿Cómo uso un espacio de nombres en mi consulta? –

+0

@Mike: vea la respuesta de TheChrisKent para ver un ejemplo. –

2

Como dijo Jon se echa en falta un espacio de nombres.

Usted puede hacer esto en C# de la siguiente manera

//Get state list using XPath 
XPathDocument xDoc = new XPathDocument(xmlPath); //Path to my file 
XPathNavigator xNav = xDoc.CreateNavigator(); 
XmlNamespaceManager xmlns = new XmlNamespaceManager(xNav.NameTable); 
xmlns.AddNamespace("p", "http://tempuri.org/Products.xsd"); 
string booksQuery = "//p:Books[p:Genre = 'Suspense']"; 
XPathNodeIterator xIter = xNav.Select(booksQuery, xmlns); 

while (xIter.MoveNext()) 
{ 
    //do stuff with xIter.Current 
} 
0

Con ETV en XML, el espacio de nombres es mucho más simple ... se puede elegir si hacer caso omiso de espacio de nombres o no.

VTDGen vg = new VTDGen(); 
if(vg.parseFile("product.xml",true)){ 
    VTDNav vn = vg.getNav(); 
    AutoPilot ap = new AutoPilot(vn); 
    ap.selectXPath("Produt[Genre='suspence']"); 
    int i = -1; 
    while ((i = ap.evalXPath()) != -1) 
    { 
        // processing logic 
    } 
}