2011-01-18 10 views
6

Oto doc przykład XML, który pasuje do jednego jestem uzyskiwanie informacji od:C# XPath help - Expression nie działa

<?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> 

Oto mój kod, aby uzyskać wszystkie książki z gatunku suspensu:

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

Próbowałem kilku kwerend, w tym Products/Books[Genre = \"Suspense\"], Products/Books, ./Books i Books. Mój xIter zawsze ma zero przedmiotów.

Jestem nowy w XPath, więc jestem pewien, że to naprawdę prosty błąd, ale może nie. Wiem, że mogę uzyskać DataSet z tabelami [Movies] i [Books] poza tym plikiem XML przy użyciu myDataSet.ReadXml(myXmlPathString);, więc plik XML nie jest uszkodzony. Jeśli to pomaga każdemu.

Moje pytanie ... co robię źle?

+0

Czy próbowałeś pojedynczych cytatów? np. Gatunek = \ "Napięcie"? – funkymushroom

+0

znacznik końcowy ma zmienioną obudowę – Rozuur

+0

@Rozuur - Przepraszam, literówka. Naprawione. @Funkymushroom - Nie zrobiłem. Spróbuję tego. –

Odpowiedz

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

Wzniesiono mianowicie, że dostał się tam pierwszy około 30sekund :-( –

+0

@Andy, Dzięki .Niko nikt z nas nie może konkurować z Jonem Skeetem :) – theChrisKent

+0

Twoje opowiadanie mi; ten człowiek jest maszyną! –

6

Poszukujesz elementu o nazwie Książki, który nie znajduje się w przestrzeni nazw. Element Products ustawia domyślny obszar nazw dla tego elementu i wszystkich jego potomków. Musisz użyć przestrzeni nazw w XPath ... lub użyć innego podejścia do zapytań, takiego jak LINQ do XML. (Osobiście uważam LINQ do XML znacznie łatwiejsze niż do czynienia z XPath - zwłaszcza, gdy trzeba uzyskać nazw związanych.)

+0

Jak możemy użyć funkcji rozpoznawania nazw za pomocą XPath? Dzięki. – Rozuur

+0

Niestety jestem ograniczony do .NET 2.0 dla tego projektu. Jak korzystać z przestrzeni nazw w moim zapytaniu? –

+0

@Mike: Zobacz odpowiedź The Chrismus na przykład. –

2

Jak powiedział Jon brakuje przestrzeni nazw.

Można to zrobić w C# następująco

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

Z VTD-XML, przestrzeń nazw jest znacznie prostsze ... można wybrać, czy ignorować nazw lub nie.

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 
    } 
}