chrisen
Goto Top

XML - XSLT Formatierung mehrere verschiedene Werte

Hallo zusammen,
ich habe eine Frage zur Konvertierung eines XML Dokuments mit XSLT in ein anderes XML Dokument.

Es geht darum irgendwie eine Abfrage mit herein zu bekommen, die das folgendes Problem löst.

Code der Konvertiert werden soll:

<?xml version="1.0" standalone="yes"?>  
<DocumentElement>
  <article>
    <ordernumber>Nummer</ordernumber>
    <mainnumber>Nummer</mainnumber>
    <ItmsGrpNam>Art</ItmsGrpNam>
    <name>Name</name>
    <suppliername>Hersteller</suppliername>
    <active>1</active>
    <Price>0.000000</Price>
    <propertyGroupName>1A</propertyGroupName>
    <propertyOptionName>1B</propertyOptionName>
    <propertyValueName>1C</propertyValueName>
    <propertyGroupName>2A</propertyGroupName>
    <propertyOptionName1>2B</propertyOptionName1>
    <propertyValueName1>2C</propertyValueName1>
    <propertyGroupName>3A</propertyGroupName>
    <propertyOptionName2>3B</propertyOptionName2>
    <propertyValueName2>3C</propertyValueName2>
  </article>
</DocumentElement>

Es geht um die Auflistung der Propertys (Group, Option,Value).

Diese sollten danach so aussehen:

<propertyValue>
		<propertyGroupName>1A</propertyGroupName>
		<propertyValueName>1B</propertyValueName>
		<propertyOptionName>1C</propertyOptionName>
</propertyValue>
<propertyValue>
		<propertyGroupName>2A</propertyGroupName>
		<propertyValueName>2B</propertyValueName>
		<propertyOptionName>2C</propertyOptionName>
</propertyValue>
<propertyValue>
		<propertyGroupName>3A</propertyGroupName>
		<propertyValueName>3B</propertyValueName>
		<propertyOptionName>3C</propertyOptionName>
</propertyValue>

Bein bisheriger Ansatz ist der hier:

<?xml version="1.0" encoding="UTF-8"?>  
<xsl:stylesheet version="1.0"  
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />  
<xsl:template match="/">  
  <Root>
  <articles>
    <xsl:for-each select="DocumentElement/article">  
      <article>
	  <ordernumber><xsl:value-of select="ordernumber"/></ordernumber>  
	  <mainnumber><xsl:value-of select="mainnumber"/></mainnumber>  
	  <name><xsl:value-of select="name"/></name>  
	  <supplier><xsl:value-of select="suppliername"/></supplier>  
	  <tax>19</tax>
	  <prices>
	  <price>
		<price><xsl:value-of select="Price"/></price>  
	  </price>
	  </prices>
	  <active><xsl:value-of select="active"/></active>  
	  <category>
		<categories>
		<xsl:choose>
		<xsl:when test="ItmsGrpNam='Lager'">39</xsl:when>  
		<xsl:when test="ItmsGrpNam='Transistor'">40</xsl:when>  
		<xsl:when test="ItmsGrpNam='Dichtring'">41</xsl:when>  
		<xsl:when test="ItmsGrpNam='Schütz'">42</xsl:when>  
		</xsl:choose>
		
		</categories>
		</category>
		<propertyValue>
			<propertyGroupName><xsl:value-of select="propertyGroupName"/> </propertyGroupName>  
			<propertyOptionName><xsl:value-of select="propertyOptionName"/></propertyOptionName>  
			<propertyValueName><xsl:value-of select="propertyValueName"/></propertyValueName>  
		</propertyValue>
      </article>
    </xsl:for-each>
    </articles>
  </Root>
</xsl:template>
</xsl:stylesheet>

Das gibt natürlich nur den ersten Wert wieder raus:
<propertyValue>
		<propertyGroupName>1A</propertyGroupName>
		<propertyOptionName>1B</propertyOptionName>
		<propertyValueName>1C</propertyValueName>
</propertyValue>

Gibt es dafür eine Lösung?

Freue mich über euere Antworten!

Grüße,
chrisen

Content-Key: 314026

Url: https://administrator.de/contentid/314026

Printed on: April 18, 2024 at 23:04 o'clock

Member: colinardo
Solution colinardo Aug 31, 2016, updated at Sep 01, 2016 at 14:03:56 (UTC)
Goto Top
Hallo chrisen,
für XSLT v1.0 habe ich im Moment leider keinen Code, aber für XSLT v2.0 (ACHTUNG: nicht vom NET Framework und meinen vorherigen Skripten unterstützt) bei dem man mehr Möglichkeiten zur Gruppierung hat (for-each-group), sieht das ganze so aus:
<?xml version="1.0" encoding="UTF-8"?>  
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">  
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />  
<xsl:template match="/">  
  <Root>
  <articles>
    <xsl:for-each select="DocumentElement/article">  
      <article>
	  <ordernumber><xsl:value-of select="ordernumber"/></ordernumber>  
	  <mainnumber><xsl:value-of select="mainnumber"/></mainnumber>  
	  <name><xsl:value-of select="name"/></name>  
	  <supplier><xsl:value-of select="suppliername"/></supplier>  
	  <tax>19</tax>
	  <prices>
	  <price>
		<price><xsl:value-of select="Price"/></price>  
	  </price>
	  </prices>
	  <active><xsl:value-of select="active"/></active>  
	  <category>
		<categories>
		<xsl:choose>
		<xsl:when test="ItmsGrpNam='Lager'">39</xsl:when>  
		<xsl:when test="ItmsGrpNam='Transistor'">40</xsl:when>  
		<xsl:when test="ItmsGrpNam='Dichtring'">41</xsl:when>  
		<xsl:when test="ItmsGrpNam='Schütz'">42</xsl:when>  
		</xsl:choose>
		
		</categories>
		</category>
		<xsl:for-each-group select="*[starts-with(local-name(),'property')]" group-starting-with="*[starts-with(local-name(),'propertyGroupName')]">  
		   <propertyValue>
			<propertyGroupName><xsl:value-of select="current-group()[1]" /></propertyGroupName>  
			<propertyValueName><xsl:value-of select="current-group()[2]" /></propertyValueName>  
			<propertyOptionName><xsl:value-of select="current-group()[3]" /></propertyOptionName>  
		   </propertyValue>
		</xsl:for-each-group>
      </article>
    </xsl:for-each>
    </articles>
  </Root>
</xsl:template>
</xsl:stylesheet>
Kannst du z.B. hier testen.

Eine Bibliothek für XSLT 2.0 bekommst zu z.B. hier:
http://saxon.sourceforge.net/#F9.7HE

In der Community-Edition von AltovaXML ist auch ein Commandline-Processor für xslt2 enthalten.
Die Community Edition kannst du hier herunterladen.

Damit kannst du die Transformation dann so in der CMD durchführen:
AltovaXML.exe /xslt2 "C:\tranform.xsl" -in "C:\input.xml" -out "C:\output.xml"
Oder wenn die Community Edition installiert ist kannst du die Bibliothek auch per .NET in Powershell ansprechen:
Add-Type -Path "C:\Program Files (x86)\Altova\AltovaXML2013\Altova.AltovaXML.dll"  
$class = New-Object Altova.AltovaXML.ApplicationClass
$class.XSLT2.InputXMLFileName = 'C:\input.xml'  
$class.XSLT2.XSLFileName = 'C:\transform.xsl'  
$class.XSLT2.Execute('C:\output.xml')  
Oder auch per COM-Object und VBS/VBA:
set xml = CreateObject("AltovaXML.Application")  
xml.XSLT2.InputXMLFileName = "C:\input.xml"  
xml.XSLT2.XSLFileName = "C:\transform.xsl"  
xml.XSLT2.Execute("C:\output.xml")  
Grüße Uwe

p.s. Ach ja, bevor ich's vergesse, vielen Dank für deine Spende! face-smile
Member: colinardo
colinardo Aug 31, 2016 updated at 12:31:39 (UTC)
Goto Top
Zur Info, habe meinen Post oben noch ergänzt.
Member: chrisen
chrisen Aug 31, 2016 at 13:31:15 (UTC)
Goto Top
Hallo colinardo,

nochmal vielen Dank für deine Antwort!!

Ich versuche gerade die Bibliothek für XLST 2.0 zu installieren. Habe damit aber noch ein paar Probleme

Grüße,
chrisen

p.s. gerne ;) und danke nochmal für deine ganze Hilfe!
Member: colinardo
colinardo Aug 31, 2016 updated at 13:35:03 (UTC)
Goto Top
Ich versuche gerade die Bibliothek für XLST 2.0 zu installieren. Habe damit aber noch ein paar Probleme
Nimm die Altova-Community-Edition wie oben beschrieben, die ist am unkompliziertesten einzurichten. Installer starten, feddich.
Member: chrisen
chrisen Aug 31, 2016 updated at 13:55:30 (UTC)
Goto Top
Zitat von @colinardo:
Nimm die Altova-Community-Edition wie oben beschrieben, die ist am unkompliziertesten einzurichten. Installer starten, feddich.

Habe ich aber dann kommt immer eine Fehlermeldung: ActiveX Komponente kann kein Objekt erstellen: 'AltovaXML.Application'.
(Wenn ich das VBScript laufen lasse)
Member: colinardo
Solution colinardo Aug 31, 2016 updated at 14:31:30 (UTC)
Goto Top
Dann hast du es nicht mit Admin-Rechten installiert! Du kannst die Registrierung auch nach der Installation nachholen indem du in einer administrativen cmd in das Verzeichnis navigierst und dort den Registrierungsvorgang wiederholst
cd "C:\Program Files (x86)\Altova\AltovaXML2013"  
AltovaXML_COM.exe /regserver
Klappt das nicht, Rechner neu starten oder du machst noch was anderes falsch. Funktioniert hier unter Win7-10 wie immer einwandfrei. Virenscanner mal vorher deaktivieren.

Aber wie oben geschrieben kannst du auch direkt die exe von altova dazu verwenden (s. Beispiel oben), dann brauchst du kein VBS.
Member: chrisen
chrisen Aug 31, 2016 updated at 16:33:09 (UTC)
Goto Top
Super jetzt funktioniert es!
Hatte die Version 2016 installiert, mit der es anscheinend nicht funktioniert hat.
Member: colinardo
colinardo Aug 31, 2016 updated at 16:59:08 (UTC)
Goto Top
Zitat von @chrisen:
Super jetzt funktioniert es!
Naturalmente il mio amico.
Hatte die Version 2016 installiert, mit der es anscheinend nicht funktioniert hat.
Wozu schreibe ich die Anleitung und poste den korrekten und einzigen Link wenn du sie nicht exakt befolgst und irgendwas anderes runterlädst face-smile?! Eine 2016er Variante davon gab es nie, gäbe es sie, hätte ich diese verlinkt. Die kostenlose Community Edition ist auch nicht mehr bei Altova auf der Webseite gelistet, trotzdem kann man sie noch herunterladen. Was du da geladen hast, weiß der Geier face-wink.

Als denn frohes Schaffen noch
Uwe
Member: chrisen
chrisen Sep 01, 2016 updated at 11:36:18 (UTC)
Goto Top
Zitat von @colinardo:
Hatte die Version 2016 installiert, mit der es anscheinend nicht funktioniert hat.
Wozu schreibe ich die Anleitung und poste den korrekten und einzigen Link wenn du sie nicht exakt befolgst und irgendwas anderes runterlädst face-smile?! Eine 2016er Variante davon gab es nie, gäbe es sie, hätte ich diese verlinkt. Die kostenlose Community Edition ist auch nicht mehr bei Altova auf der Webseite gelistet, trotzdem kann man sie noch herunterladen. Was du da geladen hast, weiß der Geier face-wink.


Alles klar sorry face-smile

Ich hätte noch eine kurze Frage:
Und zwar klappt das Script nicht immer.

Bsp. hier:

XML:

<?xml version="1.0" standalone="yes"?>  
<DocumentElement>
  <article>
    <ordernumber>100096</ordernumber>
    <mainnumber>100096</mainnumber>
    <ItmsGrpNam>Gruppenname</ItmsGrpNam>
    <name>Name</name>
    <suppliername>Hersteller</suppliername>
    <PackUnit />
    <active>1</active>
    <Price>0.000000</Price>
    <propertyGroupName3>1A</propertyGroupName3>
    <propertyOptionName3>1B</propertyOptionName3>
    <propertyValueName3>1C</propertyValueName3>
    <propertyGroupName4>2A</propertyGroupName4>
    <propertyOptionName4>2B</propertyOptionName4>
    <propertyValueName4>2C</propertyValueName4>
    <propertyGroupName5>3A</propertyGroupName5>
    <propertyOptionName5>3B</propertyOptionName5>
    <propertyValueName5>3C</propertyValueName5>
    <propertyGroupName7>4A</propertyGroupName7>
    <propertyOptionName7>4B</propertyOptionName7>
    <propertyValueName7>4C</propertyValueName7>
  </article>
</DocumentElement>

XSL:

<?xml version="1.0" encoding="UTF-8"?>  
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">  
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />  
<xsl:template match="/">  
  <Root>
  <articles>
    <xsl:for-each select="DocumentElement/article">  
      <article>
	  <ordernumber><xsl:value-of select="ordernumber"/></ordernumber>  
	  <mainnumber><xsl:value-of select="mainnumber"/></mainnumber>  
	  <name><xsl:value-of select="name"/></name>  
	  <supplier><xsl:value-of select="suppliername"/></supplier>  
	  <tax>19</tax>
	  <prices>
	  <price>
		<price><xsl:value-of select="Price"/></price>  
	  </price>
	  </prices>
	  <active><xsl:value-of select="active"/></active>  
	  <category>
		<categories>
		<xsl:choose>
		<xsl:when test="ItmsGrpNam='Kat1'">39</xsl:when>  
		<xsl:when test="ItmsGrpNam='Kat2'">40</xsl:when>  
		<xsl:when test="ItmsGrpNam='Kat3'">41</xsl:when>  
		<xsl:when test="ItmsGrpNam='Kat4'">42</xsl:when>  
		</xsl:choose>
		
		</categories>
		</category>
		<xsl:for-each-group select="*[starts-with(local-name(),'property')]" group-ending-with="*[position() mod 3 = 1]">  
		   <propertyValue>
			<propertyGroupName><xsl:value-of select="current-group()[1]" /></propertyGroupName>  
			<propertyOptionName><xsl:value-of select="current-group()[2]" /></propertyOptionName>  
			<propertyValueName><xsl:value-of select="current-group()[3]" /></propertyValueName>  
		   </propertyValue>
		</xsl:for-each-group>
      </article>
    </xsl:for-each>
    </articles>
  </Root>
</xsl:template>
</xsl:stylesheet>

Ergebnis:

<?xml version="1.0" encoding="UTF-8"?>  
<Root>
   <articles>
      <article>
         <ordernumber>100096</ordernumber>
         <mainnumber>100096</mainnumber>
         <name>Name</name>
         <supplier>Hersteller</supplier>
         <tax>19</tax>
         <prices>
            <price>
               <price>0.000000</price>
            </price>
         </prices>
         <active>1</active>
         <category>
            <categories/>
         </category>
         <propertyValue>
            <propertyGroupName>1A</propertyGroupName>
            <propertyOptionName>1B</propertyOptionName>
            <propertyValueName/>
         </propertyValue>
         <propertyValue>
            <propertyGroupName>1C</propertyGroupName>
            <propertyOptionName>2A</propertyOptionName>
            <propertyValueName>2B</propertyValueName>
         </propertyValue>
         <propertyValue>
            <propertyGroupName>2C</propertyGroupName>
            <propertyOptionName>3A</propertyOptionName>
            <propertyValueName>3B</propertyValueName>
         </propertyValue>
         <propertyValue>
            <propertyGroupName>3C</propertyGroupName>
            <propertyOptionName>4A</propertyOptionName>
            <propertyValueName>4B</propertyValueName>
         </propertyValue>
         <propertyValue>
            <propertyGroupName>4C</propertyGroupName>
            <propertyOptionName/>
            <propertyValueName/>
         </propertyValue>
      </article>
   </articles>
</Root>

Woran kann das liegen?
Member: colinardo
colinardo Sep 01, 2016 updated at 12:48:00 (UTC)
Goto Top
Hmm, kann ich hier nicht bestätigen. Das ist eine simple Gruppierung der Nodes die mit property beginnen in der Reihenfolge wie sie im XML Code stehen gruppiert wird dann durch die Berechnung der Position welche nach jeder 3 Position eine neue Gruppe beginnen lässt.
Member: chrisen
chrisen Sep 01, 2016 at 13:18:04 (UTC)
Goto Top
Merkwürdigerweise passiert das auch in dem online Transformator.
Member: colinardo
colinardo Sep 01, 2016 updated at 14:04:55 (UTC)
Goto Top
Ach, Asche auf mein Haupt, die position() hat sich auf die falschen Nodes bezogen, Fehler ist oben korrigiert, sorry.
Member: chrisen
chrisen Sep 01, 2016 at 14:17:40 (UTC)
Goto Top
Ach Super!! Vielen vielen Dank!!