2016-08-05 26 views
-2

Ich kann nicht meine Xpath-Abfrage funktionieren, obwohl auf Papier sollte es richtig sein. Ich habe sogar versucht, einen einzelnen Knoten ohne das Attribut zu bekommen und konnte nicht einmal das bekommen ...C# XML XPath Query funktioniert nicht

Was mache ich falsch?

Built result trx (cml) format

var trxXml = new XmlDocument(); 
trxXml.Load(InputTrxFile); 
XmlElement root = trxXml.DocumentElement; 

var unitTestResult = trxXml.GetElementsByTagName("UnitTestResult"); 
foreach (XmlElement runinfo in unitTestResult) 
{ 
    // Find failed tests, works fine then... 
    string TestName = runinfo.GetAttribute("testName"); // works fine 
    // Want to find equivalent TestDefinitions/UnitTest 
    /* Tried 
     TestRun/TestDefinitions/UnitTest[@name='thetest'] 
     /TestRun/TestDefinitions/UnitTest[@name='thetest'] 
     TestDefinitions/UnitTest[@name='thetest'] 
     /TestDefinitions/UnitTest[@name='thetest'] 
     UnitTest[@name='thetest'] 
     variations with no attribute test JUST to get a node 
     Example http://www.csharp-examples.net/xml-nodes-by-attribute-value/ 
     */ 
    var xpath = string.Format(@"/TestRun/TestDefinitions/UnitTest[@name='{0}']", TestName); 
    XmlNode node = trxXml.SelectSingleNode(xpath);  
    XmlNode node2 = root.SelectSingleNode(xpath); 
    // These all return null 
+0

http://stackoverflow.com/documentation/xpath/2324/namespaces#t=201608050604347342848 –

Antwort

1

Jede Abfrage, die mit einem / stellt einen absoluten Pfad beginnt, das heißt es aus der Wurzel des Dokuments ist. Es scheint, dass Ihr UnitTestResult Element (zumindest) Ihre TestRun Elemente umschließt.

Damit Ihre Abfrage den aktuellen Kontext berücksichtigt, müssen Sie auf den aktuellen Kontext verweisen. Dies kann mit . ausgewählt werden.

Zweitens haben Ihre XML-Elemente alle einen Namespace, und dies muss einen Teil Ihrer Abfrage ausmachen. Ein Präfix muss zu einem Namespacemanager hinzugefügt werden, der in Ihrer Abfrage verwendet wird, und der Manager wurde an die Abfragemethode übergeben.

Also, diese zusammen nehmen, definiert das Präfix:

var manager = new XmlNamespaceManager(new NameTable()); 
manager.AddNamespace("t", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010"); 

Ihre Abfrage ändern:

./t:TestRun/t:TestDefinitions/t:UnitTest[@name='{0}'] 

und die Namespace-Manager an die Methode übergeben:

trxXml.SelectSingleNode(xpath, manager); 

XPath und XmlDocument sind jedoch Schmerzen. Dies würde alle viel einfacher in LINQ to XML sein:

var doc = XDocument.Load(InputTrxFile); 

var unitTestQuery = 
    from result in doc.Descendants(ns + "UnitTestResult") 
    let name = (string)result.Attribute("testName") 
    from unitTest in result.Descendants(ns + "UnitTest") 
    where (string)unitTest.Attribute("name") == name 
    select unitTest; 

var unitTest = unitTestQuery.Single(); 
+0

Danke für die Detailgenauigkeit und Klarheit der Antwort. Da der GetElementsByTagName ("UnitTestResult") funktionierte, nahm ich fälschlicherweise an, dass der Namespace nicht benötigt würde. –