Katkrümel: XSLT Problem mit xmlns bei Transform XML zu XML

Hallo in die Runde, ich hoffe ich bin hier richtig und jemand kann mir einen Tipp geben. Ich habe folgende Problematik: Ich soll einen Import/Exportfilter für ein Programm bauen, um Daten maschinell als XML zwischen unterschiedlichen Systemen auszutauschen. Der Importfilter funktioniert, die ankommende XML-Datei wird mit einer XSLT-Transformationsdatei in das von unserer Software verstandenes XML-Schema umgewandelt. Aber beim Exportfilter beiße ich mir gerade die Zähne aus. Die Schwierigkeit ist, dass die XML beim Export komplett umgebaut werden muss, Struktur und Elementnamen sind komplett unterschiedlich. Hier ist beispielhaft die Quell-XML:

<?xml version="1.0" encoding="UTF-8"?>  
<rootalt xmlns="programm.export" xsi:schemaLocation="programm.export export.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
  <KnotenAlt xmlns="programm.export">  
    <Element1>a</Element1>  
    <Element2>b</Element2>  
    <Element3>c</Element3> 
    ...  
  </KnotenAlt>  
</rootalt>

Die neue XML-Datei muss zwingend diese Struktur haben:

<?xml version="1.0" encoding="UTF-8"?>  
<rootNeu>  
  <KnotenNeu>
    <Unterknoten>
      <ElementNeu1>a</ElementNeu1>
    </Unterknoten>
    <Unterknoten2>
      <ElementNeu2>b</ElementNeu2>
      <ElementNeu3>c</ElementNeu3> 
     </Unterknoten2>
     ...
  </KnotenNeu>
</rootNeu>

Jetzt kommt mein Dillemma.
Das Attribut xmlns in den beiden Knoten der Quelldatei sorgt dafür, dass ich mit der XSLT entweder nur die neuen Knoten und Elemente erhalte aber keine Werte, oder mit xsl:apply-templates/ alle Werte hintereinander ausgegeben werden und keine Elementnamen. In beiden Fällen ist die ausgegebenen XML-Datei unbrauchbar. Wenn ich manuell die Attribute in der Original-XML lösche funktioniert die Umwandlung perfekt. Leider kann ich in der Software diese Attribute nicht abschalten, da sie im XSD-Schema programmtechnisch fest im Quellcode programmiert wurde. Und wegen der anderen Struktur funktioniert auch der "xsl:copy" - Trick aus anderen Foren nicht.

Wie kann ich die dieses Namespace-Problem lösen?
Hat jemand einen Rat für mich? Danke für Eure Hilfe.
Bitte verzeiht, dass ich noch nicht so bewandert in der Formatierung in diesem Forum bin.

  1. Hallo Katkrümel,

    ab XSLT 2.0 kann bei xsl:stylesheet der Vorgabe-Namensraum angegeben werden, hier also:

    xpath-default-namespace="programm.export"

    Grüße,
    Thomas

    1. Hallo Thomas,
      danke für Deinen Tipp. Es schien genau das Richtige zu sein. Das Attribut funktioniert einwandfrei im XSLT-Online Testtool.
      Leider scheint unser Programm etwas dagegen zu haben 😟.
      Ich zeige Dir mal meine XSLT-Datei:

      <?xml version="1.0" encoding="UTF-8"?>
      <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="progamm.export" version="2.0">
          <xsl:template match="/">
      		<rootNeu>
                  <xsl:apply-templates />
      		</rootNeu>
          </xsl:template>
      	<xsl:template match="KnotenAlt">
      		<KnotenNeu>
      			<Unterknoten>
      				<ElementNeu1>
      					<xsl:value-of select="Element1" />  
      				</ElementNeu1>
      			</Unterknoten>
      			<Unterknoten2>
      				<ElementNeu2>
      					<xsl:value-of select="Element2" />  
      				</ElementNeu2>
      				<ElementNeu3>
      					<xsl:value-of select="Element3" />  
      				</ElementNeu3>
      			</Unterknoten2>
      		</KnotenNeu>
      	</xsl:template>
      </xsl:transform>
      

      Wenn ich den Transfer mit dieser XSLT-Datei von der Software so ausführen lasse, erhalte ich als Ergebnis:

      <?xml version="1.0" encoding="UTF-8"?>
      <rootNeu>
      a
      b
      c
      </rootNeu>
      

      Füge ich bei xsl:apply-templates das Attribut select="KnotenAlt" hinzu, sieht das Ergebnis so aus:

      <?xml version="1.0" encoding="UTF-8"?>
      <rootNeu />
      

      Ich bin langsam am Verzweifeln. Kann es sein, dass unser Programm nur mit XSLT Version 1.0 arbeitet und wenn ja, gibt es dort auch eine Lösung für mein Problem?
      Danke schon mal für Deine Antwort.

      Gruß,
      Katkrümel

      1. Hallo Katkrümel,

        Wenn ich den Transfer mit dieser XSLT-Datei von der Software so ausführen lasse, erhalte ich als Ergebnis:

        <?xml version="1.0" encoding="UTF-8"?>
        <rootNeu>
        a
        b
        c
        </rootNeu>
        

        Füge ich bei xsl:apply-templates das Attribut select="KnotenAlt" hinzu, sieht das Ergebnis so aus:

        <?xml version="1.0" encoding="UTF-8"?>
        <rootNeu />
        

        Ich bin langsam am Verzweifeln. Kann es sein, dass unser Programm nur mit XSLT Version 1.0 arbeitet und wenn ja, gibt es dort auch eine Lösung für mein Problem?

        Mit Saxon-HE 9.8.0.7 brauchte ich unter XSLT 2.0 die zusätzliche Angabe von xpath-default-namespace bei diesem Template-Aufruf:

        <xsl:template match="KnotenAlt" xpath-default-namespace="programm.export">
          <!-- … -->
        </xsl:template>
        

        Dann erscheint die erwartete Ausgabe.

        Wenn nur ein XSLT-1.0-Prozessor verfügbar ist, dann hilft die Angabe eines "Dummy-Namespace-Prefixes" mit dem jeweiligen Namensraum, hier als "pe" deklariert:

        <?xml version="1.0" encoding="UTF-8"?>
        <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pe="programm.export"
          exclude-result-prefixes="pe" version="1.0">
          <xsl:template match="/">
            <rootNeu>
              <xsl:apply-templates/>
            </rootNeu>
          </xsl:template>
          <xsl:template match="pe:KnotenAlt">
            <KnotenNeu>
              <Unterknoten>
                <ElementNeu1>
                  <xsl:value-of select="pe:Element1"/>
                </ElementNeu1>
              </Unterknoten>
              <Unterknoten2>
                <ElementNeu2>
                  <xsl:value-of select="pe:Element2"/>
                </ElementNeu2>
                <ElementNeu3>
                  <xsl:value-of select="pe:Element3"/>
                </ElementNeu3>
              </Unterknoten2>
            </KnotenNeu>
          </xsl:template>
        </xsl:transform>
        
        

        Ergebnis:

        <?xml version="1.0" encoding="UTF-8"?>
        <rootNeu>
          <KnotenNeu>
            <Unterknoten>
              <ElementNeu1>a</ElementNeu1>
            </Unterknoten>
            <Unterknoten2>
              <ElementNeu2>b</ElementNeu2>
              <ElementNeu3>c</ElementNeu3>
            </Unterknoten2>
          </KnotenNeu>
        </rootNeu>
        
        
        

        Grüße,
        Thomas

        1. Das war der entscheidende Tipp.
          Die Programmierabteilung des Softwareherstellers hatte uns immer XSLT Version 2.0-Dateien zugesandt, obwohl der XSLT-Prozessor offenbar ein 1.0−er ist.
          Dein Tipp mit dem Dummy-Prefix war goldrichtig und die Lösung.
          Jetzt erhalte ich die Ausgabe-XML genau nach meinen Wünschen.

          Ich sage Dir ganz herzlich Danke für deine schnelle und erfolgreiche Hilfe.

          Grüße,
          Katkrümel