Thomas J.S.: XML aus XSL heraus aufrufen

Beitrag lesen

Hallo,

kannst du noch ein Beispiel-XML posten?

sicher:

Ehm ... na ja, genau das ist  - meine Meinung nach - falsch. Du versuchst Layout mit dem XML zu mischen und das auszulagern. Besser, weil logischer und besser wartbar, wäre das Layout in einem XSL-Template auszulagern.

Mit einem:
<xsl:for-each select="document('cdcatalog_liste.xml')/*">[3]
   xsl:apply-imports/
</xsl:for-each>
sollte es gehen.

Ging auch ohne. Mit ist kein Unterschied zu merken.

Mein Fehler. (Aber dein XSLT-Prozessor sollte auch meckern!)
xsl:apply-imports/ kann nur innerhalb von xsl:template verwendet werden.
Falls dir das etwas sagt: apply-import verhält sich analog zur  super()-Funktion im objektorientierten Programmierung.

Weiters - auch mein Fehler, das übergesehen zu haben - in deinem zu importierenden XSL werden die Variablen zwar verwendet, aber nicht deklariert . (auch deshalb hätte dir eigentlich der Prozessor eine Fehlermelung liefern müssen)

Der Vorteil läge für mich darin, 1. die Anzeige-Struktur von den Daten getrennt zu halten. Die Anzeige-Struktur könnte nach belieben angepasst werden.

Das machst du abern icht in dem du XML mit dem Layout mischst. Das wäre _die_ aufgabe für dein XSLT.

»»2. wäre damit auch die Wiederverwendbarkeit der Anzeige-Struktur möglich. Wenn an verschiedenen Stellen ein und die selbe Anzeigestruktur benötigt würde, bräuchte ich diese so nur einmal hinterlegen (cdcatalog_liste.xml) und rufe sie im HauptXSL nur jedesmal auf, kopiere die Elemente, die übernommen werden und ersetze die die durch Daten ersetzt werden sollen.

Für solchen Zwecke verwendet man (benannte) Templates mit Parameters.
Was du hier versuchst entzieht sich meiner Logik ;-)
Du willst, aus einem importiertem XSL nicht nur (rückwärts) auf die Funktionen im aufrufenden XSL zurückgreifen, sondern auch noch auf ein XML, das du durch das aufrufende XSL bestimmt wird, zugrifen und darin Daten ersetzen, die wiederum in einem anderen, ebenfalls durch das aufrufende XSL bestimmten, XML enthalten sind.

Ich habe keine Lösung dafür.

Ich finde es auch wesentlihc übersichtlicher so (ohne "cdcatalog_liste.xml")
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <xsl:apply-templates />
 </xsl:template>

<xsl:template match="*[name() != 'cd_liste']">
  xsl:copy
   <xsl:for-each select="@*">
    <xsl:copy />
   </xsl:for-each>
   <xsl:apply-templates />
  </xsl:copy>
 </xsl:template>

<xsl:template match="cd_liste">
  <xsl:for-each select="document('cdcatalog.xml')/catalog/cd">
   <tr>
    <td><xsl:value-of select="title" /></td>
    <td><xsl:value-of select="artist" /></td>
   </tr>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Willst du unbedingt etwas auslagern, fände ich immer noch besser so (ebenfalls ohne "cdcatalog_liste.xml"):

-------------------------------
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:include href="formatknoten.xsl" />
 <xsl:variable name="myXML" select="document('cdcatalog.xml')/catalog" />
 <xsl:template match="/">
  <xsl:apply-templates />
 </xsl:template>

<xsl:template match="*[name() != 'cd_liste']">
  xsl:copy
   <xsl:for-each select="@*">
    <xsl:copy />
   </xsl:for-each>
   <xsl:apply-templates />
  </xsl:copy>
 </xsl:template>
 <xsl:template match="cd_liste">
  <xsl:call-template name="formatnode">
   <xsl:with-param name="node" select="." />
   <xsl:with-param name="documentNode" select="$myXML/cd" />
   <xsl:with-param name="documentElements" select="$myXML/cd/title | $myXML/cd/artist" />
   <xsl:with-param name="documentNodeElementName" select="'tr'" />
   <xsl:with-param name="documentElementsElementName" select="'td'" />
  </xsl:call-template>
 </xsl:template>
</xsl:stylesheet>

-------- formatknoten.xsl --------------
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template name="formatnode">
  <xsl:param name="node" />
  <xsl:param name="documentNode" />
  <xsl:param name="documentElements" />
  <xsl:param name="documentNodeElementName" />
  <xsl:param name="documentElementsElementName" />
  <xsl:for-each select="$node">
   <xsl:for-each select="$documentNode">
    <xsl:element name="{$documentNodeElementName}">
     <xsl:for-each select="current()/*[. = $documentElements]">
      <xsl:element name="{$documentElementsElementName}">
       <xsl:value-of select="." />
      </xsl:element>
     </xsl:for-each>
    </xsl:element>
   </xsl:for-each>
  </xsl:for-each>
 </xsl:template>

</xsl:stylesheet>
-------------------------------

Grüße
Thomas