# Mit XPath auf eine XML Datei zugreifen



## Tikonteroga (18. Oktober 2011)

Hallo,

ich versuche zurzeit mit XPath und .NET bestimmte Daten aus einer XML Datei zu lesen.

Ich verwende dabei die Klasse System.Xml.XmlDocument. Ich glaube jedoch, dass ich dafür irgendwie zu blöd bin, denn wenn ich mir mit einem XPATH Ausdruck einen NodeList zurückgeben lasse, enthält diese immer 0 Elemente.

Hier mal ein Beispiel:


```
<AUTOSAR ...>
  <ADMIN-DATA>
     ...
  </ADMIN-DATA>
  <TOP-LEVEL-PACKAGES>
     ...
  </TOP-LEVEL-PACKAGES>
  ...
</AUTOSAR>
```


```
XmlNodeList nodeList = arxmlDocument.SelectNodes("/child::TOP-LEVEL-PACKAGES");
```

Was mache ich falsch ?


----------



## deepthroat (18. Oktober 2011)

Hi.

Das / ist das Dokument Element. Dieses Element hat immer genau einen Kindknoten: das Root-Element (hier AUTOSAR).

Also

```
/child::AUTOSAR/child::TOP-LEVEL-PACKAGES
```
oder natürlich einfach

```
/AUTOSAR/TOP-LEVEL-PACKAGES
```
Gruß


----------



## Tikonteroga (18. Oktober 2011)

Hallo,

danke für die schnelle Antwort. In der Form hatte ich es auch schon versucht, dies hatte auch 0 Elemente zurückgegeben.

Ich habe es eben auch nochmal wiederholt, wieder das gleiche ...


----------



## deepthroat (18. Oktober 2011)

Tikonteroga hat gesagt.:


> Hallo,
> 
> danke für die schnelle Antwort. In der Form hatte ich es auch schon versucht, dies hatte auch 0 Elemente zurückgegeben.
> 
> Ich habe es eben auch nochmal wiederholt, wieder das gleiche ...


Bei mir funktioniert es wie erwartet.

Es werden nicht zufällig Namensräume verwendet?

Gruß


----------



## Tikonteroga (18. Oktober 2011)

Was mir auch aufgefallen ist, ist das folgendes funktioniert.


```
/*
```

Aber folgendes nicht funktioniert.


```
/AUTOSAR
```


----------



## deepthroat (18. Oktober 2011)

Vermutlich werden in dem XML Dokument Namensräume verwendet. Du mußt erstens einen Präfix für den Namensraum definieren und dann natürlich den Namensraum auch verwenden:

```
/ns:AUTOSAR
```
Gruß


----------



## Tikonteroga (18. Oktober 2011)

Hallo,

ich habe jetzt schon einiges versucht, erhalte dann aber eine Exception.

Ich habe mal einen ausgeschwarzten Root angehängt.


```
<AUTOSAR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="..." xsi:schemaLocation="..." T="...">
```


----------



## deepthroat (18. Oktober 2011)

Siehe http://msdn.microsoft.com/en-us/library/ms950779.aspx


----------



## Tikonteroga (18. Oktober 2011)

Also in meinem XML Dokument wird zwar ein Namensraum definiert, aber ihm wird kein Prefix zugewiesen. Ich kann also keinen Prefix in den XPath-Ausdruck einbauen.

Aber wenn ich einen XPath-Ausdruck ohne Prefix verwende, erhalte ich eine leere Menge ...

Ich weiss jetzt immernoch nicht woran es liegt. Wenn ich das Problem über Google, über das ich diesen Artikel auch schon gefunden hatte, hätte lösen können, hätte ich nicht hier gepostet ...


----------



## deepthroat (18. Oktober 2011)

Es ist völlig egal welcher Präfix im XML Dokument für einen Namensraum vereinbart wird. Vereinbare einfach einen (siehe das Codebeispiel) und verwende ihn.

Gruß


----------



## Tikonteroga (18. Oktober 2011)

Hallo,

danke für den Hinweis.

Ich konnte es nun so lösen.


```
XmlDocument arxmlDocument = new XmlDocument();                      //Speicher reservieren

try
{
     arxmlDocument.Load(this.arxml);                                                //ARXML Datei einlesen

     XmlNamespaceManager arxmlNamespaceManager 
          = new XmlNamespaceManager(arxmlDocument.NameTable);

     string namespaceURI 
          = arxmlDocument.DocumentElement.NamespaceURI;               //Namensraum lesen

     arxmlNamespaceManager.AddNamespace("ns", namespaceURI);      //Prefix für Namensraum festlegen

     XmlNodeList nodeList = arxmlDocument
          .SelectNodes("/ns:AUTOSAR", arxmlNamespaceManager);         //Root-Knoten auswählen

     foreach (XmlNode node in nodeList)
     {
          System.Console.WriteLine(node.Name);                                 //Root-Knoten über Konsole ausgeben
     }
}
catch
{
     throw;
}
finally
{
     arxmlDocument.RemoveAll();                                      //Speicher freigeben
}
```

Gibt es da was auszusetzen ?


----------



## deepthroat (18. Oktober 2011)

Warum liest du denn den Namensraum aus dem Dokument aus?

Normalerweise sollte man doch wissen um welche Art von Dokument es sich handelt und ebenfalls den Namensraum kennen um den es geht.

So würdest du beliebige Dokumente verarbeiten, die nicht mal im entferntesten etwas mit deinem eigentlichen Zieldokument zu tun haben...

Gruß


----------



## Tikonteroga (18. Oktober 2011)

Hmm ich bin davon ausgegangen, dass ich die Dokumente, die ich verarbeite letztendlich vorher auf das zugehörige XML-Schema validiere.

Und wollte halt vermeiden in meinem Code zu viele String Literale zu verwenden. Da meckert glaub sonst FxCop ...


----------



## Tikonteroga (26. Januar 2012)

Hallo,

ich habe aktuell folgende Problemstellung.


```
<AR-PACKAGE>
   <ELEMENTS>
      <FRAME/>
      <FRAME/>
      <FRAME/>
   </ELEMENTS>
</AR-PACKAGE>
<AR-PACKAGE>
   <ELEMENTS>
      <SYSTEM-SIGNAL/>
      <SYSTEM-SIGNAL/>
      <SYSTEM-SIGNAL/>
   </ELEMENTS>
</AR-PACKAGE>
<AR-PACKAGE>
   <ELEMENTS>
      <COMPU-METHOD/>
      <COMPU-METHOD/>
      <COMPU-METHOD/>
   </ELEMENTS>
</AR-PACKAGE>
```

Ich habe als eine Sequenz der Knoten AR-PACKAGE. Jeder Knoten AR-PACKAGE enthält einen Knoten ELEMENTS. Der Knoten ELEMENTS kann entweder eine Sequenz aus FRAME, SYSTEM-SIGNAL oder COMPU-METHOD enthalten kann.

Ist es möglich über X-PATH alle Knoten mit dem Namen FRAME zu erhalten, wenn ich davon ausgehen muss dass die Reihenfolge der AR-PACKAGE Knoten zufällig sein kann oder muss ich hier alle AR-PACKAGE Knoten in einer Schleife (foreach) durchsuchen ?


----------



## deepthroat (26. Januar 2012)

Hi.

Ich verstehe nicht wo das Problem ist. 

Mit 
	
	
	



```
AR-PACKAGE/ELEMENTS/FRAME
```
selektierst du alle FRAME Knoten (ausgehend vom Kontextknoten), die unterhalb von AR-PACKAGE und unterhalb von ELEMENTS liegen...

War das deine Frage? 

Gruß


----------



## Tikonteroga (26. Januar 2012)

Hallo,

also folgender Code gibt eine leere Menge zurück, also eine XmlNodeList mit Count=0.


```
XmlNamespaceManager arxmlNamespaceManager = new XmlNamespaceManager(arxmlDocument.NameTable);

string namespaceURI = arxmlDocument.DocumentElement.NamespaceURI; 
              
arxmlNamespaceManager.AddNamespace("ns", namespaceURI);

XmlNodeList frameNodes = arxmlDocument.SelectNodes("/ns:AUTOSAR/ns:TOP-LEVEL-PACKAGES/ns:AR-PACKAGE/ns:ELEMENTS/ns:FRAME", arxmlNamespaceManager);
```

Ich hatte jetzt angenommen, dass dies so ist, weil bei dieser Abfrage nur das erstele Element AR-PACKAGE ausgewertet wird und die Sequence von FRAME nicht im ersten Element AR-PACKAGE enthalten ist.


----------



## deepthroat (26. Januar 2012)

Tikonteroga hat gesagt.:


> Hallo,
> 
> also folgender Code gibt eine leere Menge zurück, also eine XmlNodeList mit Count=0.


Das kann nun verschiedene Ursachen haben. Als erstes würde ich auf falsche Namensräume tippen.

Mach ein konkretes Minimalbeispieldokument.

Gruß


----------



## Tikonteroga (26. Januar 2012)

Hallo,

also ich habe jetzt mal anstelle von...


```
"/ns:AUTOSAR/ns:TOP-LEVEL-PACKAGES/ns:AR-PACKAGE/ns:ELEMENTS/ns:FRAME"
```

... folgenden XPath Ausdruck vervendet.


```
"/ns:AUTOSAR/ns:TOP-LEVEL-PACKAGES/ns:AR-PACKAGE/ns:ELEMENTS/ns:UNIT"
```

Dabei ist das XML-Element AR-PACKAGE, das im Child-Element ELEMENTS die Child-Elemente UNIT enthält, das erste (1.) in der Sequence von AR-PACKAGE-Elementen im Element TOP-LEVEL-PACKAGES.

Wenn ich also das Element UNIT addressiere erhalte ich 27 Elemente zurück.


----------



## deepthroat (26. Januar 2012)

Tikonteroga hat gesagt.:


> also ich habe jetzt mal anstelle von...
> 
> 
> ```
> ...


Ja, und?! Was willst du damit sagen?


----------



## Tikonteroga (26. Januar 2012)

Naja letztendlich wollte ich nachfragen, wie ich den XPath Ausdruck beschreiben muss, damit ich aus einer Sequence aus *AR-PACKAGE* Elementen das oder die *AR-PACKAGE*Elemente abrufen kann, die als Child-Element von *ELEMENTS* eine Sequence von *FRAME*-Elementen hat.


----------



## deepthroat (26. Januar 2012)

Tikonteroga hat gesagt.:


> Naja letztendlich wollte ich nachfragen, wie ich den XPath Ausdruck beschreiben muss, damit ich aus einer Sequence aus *AR-PACKAGE* Elementen das oder die *AR-PACKAGE*Elemente abrufen kann, die als Child-Element von *ELEMENTS* eine Sequence von *FRAME*-Elementen hat.



Du willst also eine Knotenmenge von AR-PACKAGE Elementen erhalten?

```
AR-PACKAGE[ELEMENTS/FRAME]
```
Gruß


----------



## Tikonteroga (26. Januar 2012)

Hallo,

vielen Dank für die Antwort.

Ich habe deinen Vorschlag gleich mal ausprobiert.


```
XmlNodeList arPackageNodes = arxmlDocument.SelectNodes("/ns:AUTOSAR/ns:TOP-LEVEL-PACKAGES/ns:AR-PACKAGE[ns:ELEMENTS/ns:FRAME]", arxmlNamespaceManager);
```

Ich habe jedoch 0 Elemente zurückbekommen. Ich erwarte aber 1 Element.

Wenn ich folgenden Aufruf mache erhalten ich eine Menge von 10 Elementen zurück.


```
XmlNodeList arPackageNodes = arxmlDocument.SelectNodes("/ns:AUTOSAR/ns:TOP-LEVEL-PACKAGES/ns:AR-PACKAGE[ns:ELEMENTS]", arxmlNamespaceManager);
```

Dieser Aufruf verhält sich gleich wie folgender Aufruf.


```
XmlNodeList arPackageNodes = arxmlDocument.SelectNodes("/ns:AUTOSAR/ns:TOP-LEVEL-PACKAGES/ns:AR-PACKAGE", arxmlNamespaceManager);
```


----------



## deepthroat (26. Januar 2012)

Ich dachte FRAME müßte groß geschrieben werden?!


----------



## Tikonteroga (26. Januar 2012)

Sorry, das war ein Tipp-Fehler.

Habe es eben auch nochmal mit FRAME geprüft.


----------



## deepthroat (26. Januar 2012)

Erstelle ein konkretes Minimalbeispieldokument.


----------



## Tikonteroga (26. Januar 2012)

Hallo,

ich habe einen Auszug erstellt und hochgeladen.


----------



## deepthroat (26. Januar 2012)

Also bei mir funktioniert das problemlos. Powershell:

```
> $doc = New-Object System.Xml.XmlDocument
> $doc.Load("example.xml")
> $ns = @{"ns" = $doc.DocumentElement.NamespaceURI}
> Select-Xml -Xpath "/ns:AUTOSAR/ns:TOP-LEVEL-PACKAGES/ns:AR-PACKAGE[ns:ELEMENTS/ns:FRAME]" -namespace $ns $doc
namespace $ns $doc

Node                                    Path                                    Pattern
----                                    ----                                    -------
AR-PACKAGE                              InputStream                             /ns:AUTOSAR/ns:TOP-LEVEL-PACKAGES/ns...
```
Es wird genau ein AR-PACKAGE gefunden.

Du mußt irgendetwas anderes falsch machen.

Verarbeitest du auch das richtige Dokument? Hast du es auch mit dem Beispieldokument probiert bevor du es hochgeladen hast?

Gruß


----------



## Tikonteroga (30. Januar 2012)

Hallo,

also mit dem Beispieldokument erhalten ich auch 1 Element als Ergebnismenge.

Ich werde mir jetzt nochmal das original anschauen, vielleicht hab ich ja irgendwas übersehen ...


----------

