# XML Tansformation



## RicoTT (7. Jan 2016)

Hallo zusammen,
ich bin gerade dabei eine xslt-Datei zu erstellen
um folgende Transfomation einer Xml in eine
andere Xml durchzuführen.

Einzelne Propertys sind durch diese Zeile abgetrennt:
<PropertyFormattingRAlign="*1*" FormattingLength="*32*"FormattingType="*0*">
Und werden so dargestellt:
<PropertyName>Anschlussbezeichnung1</PropertyName>
<PropertyValue>1</PropertyValue></Property>

Ziel ist es die einzelnen Propertys in folgendes Format zu überführen:
<ConnectorNr>1</ConnectorNr>

Hat jemand eine Idee, wie dies zu realisieren ist?

Vielen Dank im voraus!


----------



## kneitzel (7. Jan 2016)

Also ich verstehe das noch nicht ganz, da ich das "ConnectorNr" nirgends sehe - oder ist dies ein Beispiel für ein PropertyName der im ersten Teilstück "Anschlussbezeichnung1" ist?

Und wie ist der Aufbau des XML Dokuments genau? Hast Du da evtl. ein xsd für? Das PropertyFormatingRAlign kann ich derzeit nicht zuordnen - und die PropertyName und PropertyValue scheinen innerhalb eines Property-Nodes zu sein, denn den schliesst Du ja noch.

Im Augenblick noch etwas zu unklar, um Dir da dann ein xslt an die Hand geben zu können. Wobei das jetzt auf den ersten Blick erst einmal trivial ist, wenn das ConnectorNr ein Propertyname und die 1 der zugehörige PropertyVale Wert ist. Das einzig komplizierte könnte die Erstellung eines Nodes aus einem Wert sein. Dazu wird <xsl:element> verwendet (http://www.w3schools.com/xsl/el_element.asp). 

Somit hätte man da ein template, dass auf die Properties matcht und dann kannst Du ein xsl:element mit dem name <xsl:value-of select="PropertyName"> und dann als Inhalt das xsl:value-of select="PropertyValue"> nehmen.  (Ist jetzt aber alles aus dem Kopf geschrieben, daher alles nur als Hinweis zu sehen!)

Generelle Empfehlung wäre, mal eine xslt Einführung anzusehen (z.B. http://www.w3schools.com/xsl/)

Meine Links sind auf englisch - ich hoffe, dass dies kein Problem ist. Auf Deutsch wird es da aber auch einiges geben.

Wenn Du mehr Details der ein beispiel-XML lieferst, dann können wir das gerne einmal anschauen. Auch das Ziel müsste  genauer definiert werden, denn ein XML Dokumente hat einen Root-Node. Wenn Du mehrere Properties nur untereinander setzt, dann ist das kein XML Dokument sondern ein XML Fragment. Erzeugen kann man das natürlich problemlos, wenn es das ist, was Du willst.

Konrad


----------



## RicoTT (7. Jan 2016)

Hallo Konrad,
vielen Dank für deine Antwort.

Ich habe mir bereits ein Tutorial angesehen,
allerdings trotzdem noch keine Lösung für mein Problem gefunden.

Wie du richtig erkannt hast, handelt es sich nur um 
ein Fragment, da ich eben dieses bestimmte Problem lösen möchte. 
Ein komplettes xslt erwarte ich gar nicht 

Nun aber nochmal zu meinem eigentlichen Problem:

die Ausgangs-XML wird mir von einem Programm erzeugt
(ich habe also keinen Einfluss auf dessen Schema) und
soll in ein vorgegebenes Schema umgewandelt werden,
um dann weiterverarbeitet zu werden.
Zum Beispiel sei gesagt, dass das Programm den Namen Anschlussbezeichnung1
vergibt, in der späteren XML dies aber als ConnectorNr bezeichnet sein soll.
Der zugehörige Wert ist 1 und soll wie oben dargestellt werden.

Bisher habe ich aber nur Beispiele gefunden, in denen
ein Element mit Wert übergeben wird, ich habe das Problem
dass der Name und der Wert in zwei einzelnen Elementen stehen.


----------



## kneitzel (7. Jan 2016)

Also ein Programm sollte immer eine Ausgabe in einem klar definierten Schema erzeugen. Nur so kann diese Ausgabe auch sinnvoll verwendet werden. Wir gehen bei uns immer so weit, dass wir auch klare xsd Dateien mit Namespaces erstellen, denn so ist klar dokumentiert, was für eine Ausgabe von uns kommt.

Also selbst wenn das ganze Schema nicht fest definiert ist, musst Du Dich auf gewisse Dinge verlassen können. Du musst ja erkennen können, was Deine Anschlussbezeichnung1 ist.

Also was man in einem xslt machen kann ist z.B.
Input ist ein Block

```
<Property>
  <PropertyName>Anschlussbezeichnung1</PropertyName>
  <PropertyValue>(Wert)</PopertyValue>
</Property>
```
Und Ausgabe ist dann ein

```
<ConnectorNr>(Wert)</ConnectorNr>
```

Dann müsste man nur nach Property/PropertyName mit Wert Anschlussbezeichnung1 suchen und da in der Ausgabe dann

```
<ConnectorNr><xsl:value-of select="Property/PropertyValue"/> </ConnectorNr>
```
schreiben.
Die suche mit dem festen Wert drin habe ich so noch nicht gebraucht und kann ich daher nicht aus dem Kopf schreiben. Was aber auf jeden Fall geht ist der einfache Match auf Property Nodes und dann mittels <xsl:if> die Prüfung, ob PropertyName eben Anschlussbezeichnung1 ist.

Das wäre evtl. auch lesbarer, wenn Du so mehrere Properties ausgeben willst. Aber ohne das fertige XSLT zu sehen, wird es etwas schwer.

Gib doch einfach einmal ein Beispiel XML - dann könnte ich evtl. ein xslt erstellen für Dich. Dann hättest Du einen ersten Ansatz. (Aber zeitnahe Erstellung kann ich nicht garantieren. Wird evtl. erst am Wochenende etwas und auch nur, wenn nichts dazwischen kommt!)

Konrad


----------



## kneitzel (7. Jan 2016)

Was ich da mal bezüglich des von Dir gelieferten XML und des Wunsch-Outputs angefangen habe, wäre:


```
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">

    <Hil_Test_Bench xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="HiL_XML_Schema.xsd" >
      <io_layer>
        <PIN>
          <!-- Now we get one line after the other -->
          <xsl:for-each select="//Line">
            <!-- We check if there is a value inside the Property[position()=0]/PropertyValue -->
            <xsl:if test="string-length(Label/Property[1]/PropertyValue) &gt; 0">
              <Test>
                <xsl:value-of select="Label/Property[1]/PropertyValue"/>
              </Test>
            </xsl:if>
          </xsl:for-each>
        </PIN>
      </io_layer>
    </Hil_Test_Bench>

  </xsl:template>

</xsl:stylesheet>
```

Daran kannst Du sehen:
a) wie ich die Zielstruktur simple aufgebaut habe - nur am ende habe ich halt nur den Test Node eingefügt.
b) Wie ich auf die Properties zugegriffen habe - diese sind ja in einer festen Reihenfolge, so dass Zugriff mit [1] [2] u.s.w. möglich ist.
c) Die Prüfung, ob in dem Datensatz Daten sind. 

Wenn Du nicht über die Position sondern über den PropertyName zugreifen möchtest, dann geht das auch mittels:

```
<xsl:value-of select="Label/Property[PropertyName='Anschlussbezeichnung 1']/PropertyValue" />
```
was die PropertyValue von der Property ausgibt, dessen PropertyName Node gleich 'Anschlussbezeichnung 1' ist.

Offen ist noch die Bearbeitung des zusammengesetzten Wertes. Hier würde ich erst den Wert der PropertyValue in eine Variable schreiben und dann mittels substring-before und substring-after die beiden Teile vor und nach dem Leerzeichen bekommen.

Damit sollte Dein Problem gelöst sein, oder?

Konrad


----------



## RicoTT (7. Jan 2016)

Du hast mir fürs Verständnis damit auf jeden Fall ordentlich weiter geholfen.

Hab allerdings gerade mal das xsl, so wie du es geschrieben hast ausprobiert
und da wird leider kein Element gefunden. 
Sicher, dass der Zugriff mit den geklammerten Zahlen möglich ist?


----------



## kneitzel (7. Jan 2016)

Jo, wie führst Du das aus? Ich habe das im Visual Studio durchlaufen lassen und das Ergebnis bekommen (Dateien sind zu .txt geändert).

Wie du siehst habe ich da den Zugriff mit PropertyName auch getestet...


----------



## RicoTT (8. Jan 2016)

Ich habe die xslt in die xml eingebunden und die XML dann einfach im Browser geöffnet.

Edit:
Habe die Transformation jetzt auch noch einmal in Eclipse versucht, da kommt das Selbe raus wie bei dir. 

Wenn ich allerdings die Quelle mit mehr Daten füttere, bleibt das Element "Pin" in der Ausgabe leer...


----------



## kneitzel (8. Jan 2016)

Da musst du mal schauen, wo die pin in dem XML Dokument steht und ob das im Transform richtig angegeben ist.


----------

