# XPath Adressierung



## NNiko (8. Sep 2009)

Hallo, ih habe hier eine mit StarUML erstellte XML Datei und will jetzt mithilfe von XPath jeden Knoten auslesen der beim Attribut name einen Inhlat hat.

[XML]<?xml version = "1.0" encoding = "UTF-8"?>
<XMI xmi.version = "1.1" xmlns:UML="href://org.omg/UML/1.3" timestamp = "Mon Sep 07 17:39:11 2009">
<XMI.header>
  <XMI.documentation>
    <XMI.owner></XMI.owner>
    <XMI.contact></XMI.contact>
    <XMI.exporter>StarUML.XMI-Addin</XMI.exporter>
    <XMI.exporterVersion>1.0</XMI.exporterVersion>
    <XMI.notice></XMI.notice>
  </XMI.documentation>
  <XMI.metamodel xmi.name = "UML" xmi.version = "1.3"/>
 </XMI.header>
<XMI.content>
<UML:Model xmi.id="UMLProject.1">
  <UML:Namespace.ownedElement>
    <UMLackage xmi.id="UMLPackage.2" name="Package1" visibility="public" isSpecification="false" namespace="UMLProject.1" isRoot="false" isLeaf="false" isAbstract="false">
      <UML:Namespace.ownedElement>
        <UML:StateMachine xmi.id="UMLStateMachine.3" name="StateMachine1" visibility="public" isSpecification="false" context="UMLPackage.2">
          <UML:StateMachine.top>
            <UML:CompositeState xmi.id="UMLCompositeState.4" name="TOP" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" isConcurrent="false">
              <UML:CompositeState.subvertex>
                <UML:FinalState xmi.id="UMLFinalState.5" name="FinalState1" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.16"/>
                <UML:SimpleState xmi.id="UMLCompositeState.6" name="0 - neuer Auftrag" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.17 UMLTransition.31 UMLTransition.32" incoming="UMLTransition.16 UMLTransition.28"/>
                <UML:SimpleState xmi.id="UMLCompositeState.7" name="1 - Fahrt zum Kunden" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.18 UMLTransition.19" incoming="UMLTransition.17"/>
                <UML:SimpleState xmi.id="UMLCompositeState.8" name="5 - Ankunft Kunde" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.20 UMLTransition.21" incoming="UMLTransition.18 UMLTransition.31"/>
                <UML:SimpleState xmi.id="UMLCompositeState.9" name="6 - Beginn Entladung" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.22 UMLTransition.24" incoming="UMLTransition.20 UMLTransition.23 UMLTransition.25"/>
                <UML:SimpleState xmi.id="UMLCompositeState.10" name="7 - Ende Entladung" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.23 UMLTransition.26 UMLTransition.27" incoming="UMLTransition.22"/>
                <UML:SimpleState xmi.id="UMLCompositeState.11" name="8 - Beginn Kundenpause" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.25" incoming="UMLTransition.24"/>
                <UML:SimpleState xmi.id="UMLCompositeState.12" name="15 - Auftrag erledigt" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.29" incoming="UMLTransition.26"/>
                <UML:SimpleState xmi.id="UMLCompositeState.13" name="16 - Auftrag abbrechen" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.30" incoming="UMLTransition.19 UMLTransition.21 UMLTransition.27 UMLTransition.32"/>
                <UML:FinalState xmi.id="UMLFinalState.14" name="FinalState2" visibility="public" isSpecification="false" container="UMLCompositeState.4" incoming="UMLTransition.29 UMLTransition.30"/>
                <UMLseudostate xmi.id="UMLPseudostate.15" name="Initial1" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.28" kind="initial"/>
              </UML:CompositeState.subvertex>
            </UML:CompositeState>
          </UML:StateMachine.top>
          <UML:StateMachine.transitions>
            <UML:Transition xmi.id="UMLTransition.16" name="" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLFinalState.5" target="UMLCompositeState.6"/>
            <UML:Transition xmi.id="UMLTransition.17" name="1; Auftrag angenommen, Dialog1" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.6" target="UMLCompositeState.7"/>
            <UML:Transition xmi.id="UMLTransition.18" name="" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.7" target="UMLCompositeState.8"/>
            <UML:Transition xmi.id="UMLTransition.19" name="" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.7" target="UMLCompositeState.13"/>
            <UML:Transition xmi.id="UMLTransition.20" name="6, Entladung starten, Dialog3" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.8" target="UMLCompositeState.9"/>
            <UML:Transition xmi.id="UMLTransition.21" name="16, Auftrag ablehnen, Dialog2" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.8" target="UMLCompositeState.13"/>
            <UML:Transition xmi.id="UMLTransition.22" name="" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.9" target="UMLCompositeState.10"/>
            <UML:Transition xmi.id="UMLTransition.23" name="7, Entladung beendet, Dialog4" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.10" target="UMLCompositeState.9"/>
            <UML:Transition xmi.id="UMLTransition.24" name="" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.9" target="UMLCompositeState.11"/>
            <UML:Transition xmi.id="UMLTransition.25" name="8, Pause, Dialog5" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.11" target="UMLCompositeState.9"/>
            <UML:Transition xmi.id="UMLTransition.26" name="" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.10" target="UMLCompositeState.12"/>
            <UML:Transition xmi.id="UMLTransition.27" name="16, Auftrag ablehnen, Dialog2" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.10" target="UMLCompositeState.13"/>
            <UML:Transition xmi.id="UMLTransition.28" name="" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLPseudostate.15" target="UMLCompositeState.6"/>
            <UML:Transition xmi.id="UMLTransition.29" name="Auftrag erledigt, Dialog6" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.12" target="UMLFinalState.14"/>
            <UML:Transition xmi.id="UMLTransition.30" name="" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.13" target="UMLFinalState.14"/>
            <UML:Transition xmi.id="UMLTransition.31" name="5, Auftrag angenommen, Dialog1" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.6" target="UMLCompositeState.8"/>
            <UML:Transition xmi.id="UMLTransition.32" name="16, Auftrag ablehnen, Dialog2" visibility="public" isSpecification="false" stateMachine="UMLStateMachine.3" source="UMLCompositeState.6" target="UMLCompositeState.13"/>
          </UML:StateMachine.transitions>
        </UML:StateMachine>
      </UML:Namespace.ownedElement>
    </UMLackage>
  </UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
</XMI>
[/XML]


Momentan scheitere ich aber schon daran aus dieser UML Datei einen genauen Pfad auszulesen.
Habe mal probiert das Attribut name aus diesem Teil der XML auszulesen:

[XML]<UML:SimpleState xmi.id="UMLCompositeState.6" name="0 - neuer Auftrag" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.17 UMLTransition.31 UMLTransition.32" incoming="UMLTransition.16 UMLTransition.28"/>[/XML]


```
XPathExpression expr = xpath.compile("UML:Namespace.ownedElement//UML:StateMachine xmi.//UML:StateMachine.top//UML:CompositeState xmi.//UML:CompositeState.subvertex//UML:FinalState xmi.//UML:SimpleState xmi.//@name");
```

Diesen Pfad habe ich dafür verwendet. Er funktioniert aber nicht.
Ich bräuchte jetzt eure Hilfe. Kann mir jemand helfen einen Pfad so anzulegen, dass er mir alle Attribute durchsucht und immer dann wenn er ein Attribut name findet welches einen Inhalt hat, soll er diesen Inhalt in eine andere XML Datei schreiben.

Es würde auch passen wenn er einfach nur von jedem
[XML] <UML:SimpleState>[/XML]
das Attribut name auslesen würde und dann in ein neues Dokument speichert.
Vielen Dank schon mal


----------



## NNiko (9. Sep 2009)

Kann mir keiner einen Tip geben wir ich den Inhalt aller gleichnamigen Attribute, in dem Fall die name= Attribute auslesen kann? 
Sollte doch einfach funktionieren alle Attribute auszulesen und in eine Datei zu schreiben oder??


----------



## NNiko (9. Sep 2009)

Bin jetzt schon mal soweit, dass ich eine Zeile auslesen kann, ist es möglich mit getElementsbyTagName einfach alle gleichnamigen Elemente aufzulisten.

denn mit

```
Node firstNode = nodeList.item(0);
```
bekomme ich lediglich ein Element ausgelesen. Kann man dies so abändern, dass er einfach alle Elemente auflistet.

Mein bisheriger Code dazu

```
import java.io.*;
 import javax.xml.parsers.*;
 import org.w3c.dom.*;
 import org.w3c.dom.NodeList;
 import org.w3c.dom.Node;
 import java.io.FileNotFoundException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.Source;


import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
  public class XMLTest {

    public static void main(String[] args) throws Exception {
      XMLTest theClient = new XMLTest();
      theClient.run();
    }

    private void run() throws Exception {
      File xmlFile = null;
      xmlFile = new File( "C:/Dokumente und Einstellungen/nuesslen/Desktop/Test/statemachine.xml" );

      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();

      Document doc = builder.parse( xmlFile );


      NodeList nodeList = doc.getElementsByTagName( "UML:SimpleState" );


      Node firstNode = nodeList.item(0);
      NamedNodeMap nodemap = firstNode.getAttributes();

       
      System.out.println( nodemap.getNamedItem( "name" ).getNodeValue() );
      
       TransformerFactory.newInstance().newTransformer().transform(
                   new DOMSource(doc), new StreamResult(new FileOutputStream("C://Dokumente und Einstellungen//nuesslen//Desktop//Test//XY.XML")));
      System.out.println( nodemap.getNamedItem( "outgoing" ).getNodeValue() );
      System.out.println( nodemap.getNamedItem( "incoming" ).getNodeValue() );

    }

  }
```


----------



## ModellbahnerTT (10. Sep 2009)

du verwendet gar kein xpath sondern hangelst dich per DOM durch das dokument.

der xpath ausdruck für alle knoten mit name-attribut wäre einfach:
"//[@name]"

bzw

"//UML:SimpleState/@name" für alle Namen der SimpleState elemente


XPATH Tutorial:
XPath Tutorial


----------



## NNiko (10. Sep 2009)

Habs jetzt mit hilfe aus dem Forum hier schon soweit gebracht alle für mich Interessanten Daten auszulesen.
Mit folgendem Code:

```
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;

public class Beta
{
    private final String    stateFile   = "...TEST1.xml";
    private DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    private XPathFactory factoryX = XPathFactory.newInstance();
    private XPath xpath = factoryX.newXPath();

    public static void main(String[] args) throws Exception
    {
        Beta theClient = new Beta();
        theClient.run();
    }

    private void run()
    {
        File xmlFile = new File("...statemachine.xml");
        processFile(xmlFile);
    }

    private boolean processFile(File xmlFile)
    {
        System.out.println("Bearbeite \"" + xmlFile.getName() + "\"...");
        try
        {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document inDoc = builder.parse(xmlFile);
            NodeList nodeList = inDoc.getElementsByTagName("UML:SimpleState");

            factory.setNamespaceAware(true); // never forget this!
            Document outDoc = builder.parse(stateFile);


            for (int i = 0; i < nodeList.getLength(); i++)
            {
                NamedNodeMap nodemap = nodeList.item(i).getAttributes();
                String name = nodemap.getNamedItem("name").getNodeValue();
                String incoming = nodemap.getNamedItem("incoming").getNodeValue();
                String outgoing = nodemap.getNamedItem("outgoing").getNodeValue();
                System.out.println(name + "\n" + incoming + "/" + outgoing);
                outDoc = setState(outDoc, name, "NEUER_AUFTRAG");
            }

            DOMSource domSource = new DOMSource(outDoc);
            File fileOutput = new File(stateFile);
            StreamResult streamResult = new StreamResult(fileOutput);
            TransformerFactory tf = TransformerFactory.newInstance();

            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.transform(domSource, streamResult);


            System.err.println("Bearbeiten von \"" + xmlFile.getName() + "\" abgeschlossen!");
            return true;
        }
        catch (Exception e) {
            System.err.println("Bearbeiten von \"" + xmlFile.getName() + "\" fehlgeschlagen: " + e);
        }
        return false;
    }

    private Document setState(Document doc, String key, String newState) throws Exception
    {
        XPathExpression expr = xpath.compile("//MAPPINGTABLES//MAPPINGTABLE//MAPPING[@key=\"" + key + "\"]//text()");
        Object result = expr.evaluate(doc, XPathConstants.NODESET);
        NodeList nodes = (NodeList) result;

        for (int i = 0; i < nodes.getLength(); i++)
        {
            System.out.println("Alter Wert name: " + nodes.item(i).getNodeValue());
            nodes.item(i).setNodeValue(newState);
            System.out.println("Neuer Wert name: " + nodes.item(i).getNodeValue());
        }

        return doc;


    }
}
```

Jetzt habe ich nur ein Problem. Eigentlich sollte dieser Code jetzt in eine andere XML an die Stelle:

```
XPathExpression expr = xpath.compile("//MAPPINGTABLES//MAPPINGTABLE//MAPPING[@key=\"" + key + "\"]//text()");
```

den Wert NEUER_AUFTRAG schreiben


```
outDoc = setState(outDoc, name, "NEUER_AUFTRAG");
```

(sollte hiermit geschehen)

Nur leider klappt das schreiben bei mir nicht.

Die andere XML in die geschrieben werden soll ist übrigens :
[XML]<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MMI>
<MAPPINGTABLES>
  	<MAPPINGTABLE hash="key" name="ack_caption_job_2" type="map">
  		<MAPPING key="0">0</MAPPING>
  		<MAPPING key="1">1}</MAPPING>
  		<MAPPING key="2">2</MAPPING>
  		<MAPPING key="3">3</MAPPING>
  		<MAPPING key="4">4</MAPPING>
  		<MAPPING key="5">5</MAPPING>
  		<MAPPING key="6">6</MAPPING>
  		<MAPPING key="7">7</MAPPING>
  		<MAPPING key="8">8</MAPPING>
  		<MAPPING key="9">9</MAPPING>
  		<MAPPING key="10">10</MAPPING>
  		<MAPPING key="11">11</MAPPING>
  		<MAPPING key="12">12</MAPPING>
  		<MAPPING key="13">13</MAPPING>
  		<MAPPING key="14">14</MAPPING>
  		<MAPPING key="15">15</MAPPING>
  		<MAPPING key="16">16</MAPPING>
  		<MAPPING key="-1">-1</MAPPING>
  		<MAPPING key="default"/>
   	</MAPPINGTABLE>






  </MAPPINGTABLES>
</MMI>
[/XML]


----------



## ModellbahnerTT (10. Sep 2009)

du willst also den Name von simplestate

```
<UML:SimpleState xmi.id="UMLCompositeState.6" name="0 - neuer Auftrag" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.17 UMLTransition.31 UMLTransition.32" incoming="UMLTransition.16 UMLTransition.28"/>
```

mit dem key von mapping zusammenführen

```
<MAPPING key="0">0</MAPPING>
```

aber das wird so nicht gehen, du müsstest aus dem SimpleState namen erst vorne die Zahl rausparsen.

denn es gilt "0 - neuer Auftrag" != "0"


----------



## NNiko (11. Sep 2009)

Ich dachte mir, vielleicht ist es auch lösbar wenn ich es nach folgender Logik machen:
-Folgende Zeile aus der XML auslesen:
[XML]<UML:SimpleState xmi.id="UMLCompositeState.6" name="0 - neuer Auftrag" visibility="public" isSpecification="false" container="UMLCompositeState.4" outgoing="UMLTransition.17 UMLTransition.31 UMLTransition.32" incoming="UMLTransition.16 UMLTransition.28"/>[/XML]
- Wenn dann z.B. 0 - neuer Auftrag gefunden wird, bekommt er in einer weiteren von mir aus Textdatei (kann auch eine beliebige andere Datei sein) die Information was er dann in folgende XML Zeile schreiben soll:
[XML]<MAPPING key="0">0</MAPPING>[/XML]

Ich kann in dieser Textdatei dann einfügen was ich will und er schreibt es in dem Beispiel statt der 0 ins MAPPING Tag mit dem key="0"

Funktioniert also ähnlich wie ne Datenbank. Ich finde einen bestimmten Wert und wenn dieser gefunden wird soll folgender Text an folgende Stelle geschrieben werden.

Meinst du das lässt sich so einfacher lösen?


----------



## ModellbahnerTT (11. Sep 2009)

ich weiß nicht was du machen willst und warum, von daher kann ich dir auch keine lösung anbieten.

ich hab dir nur geschrieben warum dein code so nicht funktioniert, weils eben kein match gibt.

außerdem könntest du dich ruhig mal bedanken.


----------

