Thomas J.S.: Fehler im XSL?

Beitrag lesen

Hallo,

ich hab hier ein Template, das zwar funktioniert, aber nicht so wie es soll. Dabei soll eine Tabelle erstellt werden.

Hier erstmal der Quelltext:

<xsl:template match="/office:body">
xsl:choose
  <xsl:when test="descendant-or-self::table:table">
   <xsl:for-each select="descendant-or-self::table:table">
    <table>
    <xsl:for-each select="descendant-or-self::table:table-row">
     <tr>
     <xsl:for-each select="descendant-or-self::table:table-cell">
      <td>
      <xsl:for-each select="descendant-or-self::text:p">
       <table><xsl:value-of select="descendant-or-self::text:p" /></table>
      </xsl:for-each>
      </td>
     </xsl:for-each>
     </tr>
    </xsl:for-each>
    </table>
   </xsl:for-each>
  </xsl:when>
  xsl:otherwise
   <xsl:for-each select="descendant-or-self::text:p">
    <p><xsl:value-of select="descendant-or-self::text:p" /></p>
   </xsl:for-each>
  </xsl:otherwise>
</xsl:choose>
  </xsl:template>

Den Inhalt bekomme ich soweit ganz gut. Bei der Erstellung der Tabelle happerts allerdings noch irgendwo. Den Inhalt einer Tabellenzelle bekomme ich zurück, die zugehörige Tabelle jedoch nicht. Kann mir jemand sagen, was ich da falsch mache?

warum verwendest du die descendant-or-self (Nachkommen und selbst) Achse?
office:body ist ja selbst bestimmt keine table:table so wie table:table selbst keine table:table-row ist Usw.

Der einzige Fall wo diese Achse sich wirklich auswirkt ist:
<xsl:for-each select="descendant-or-self::text:p">
 <table><xsl:value-of select="descendant-or-self::text:p" /></table>
</xsl:for-each>

Wobei du hier gleich einen Fehler machst, du erzeugst nämlich für ein text:p
eine <table>textinhalt vom text:p</table> was in HTML dann zu Fehler fürhrt.
Die Achse wirklich sich auch nur aus, weil pext:p selbst ja wirklich text:p ist, aber wozu dann seine Nachkommen text:p's auswählen, wenn diese erst gar nicht geben kann?

Zudem bewirkt dein Template, dass so fern im office:body auch nur ein enziger table:table vorkommt, alles andere ignoriert wird, auch wenn vor oder nach dem table:table-Element noch andere Elemente im XML gibt.

Hier würde sich empfehlen, dass du für diese Elemente eigene Templates erstellt.

<xsl:template match="/office:body">
  <xsl:apply-templates />
 </xsl:template>

<xsl:template match="table:table">
  <table>
   <xsl:apply-templates />
  </table>
 </xsl:template>
 <xsl:template match="table:table-row">
  <tr>
   <xsl:apply-templates />
  </tr>
 </xsl:template>
 <xsl:template match="table:table-cell">
  <td>
   <xsl:apply-templates />
  </td>
 </xsl:template>
 <xsl:template match="text:p">
  <p>
   <xsl:value-of select="."/>
  </p>
 </xsl:template>

Das ist in diesem Fall nicht nur übersichtlicher, sondern hat auch den Vorteil, dass du dich nicht darum kümmern musst, ob und wo im office:body table pder p vorkommt, darum kümmert sich der XSL-Prozessor beim apply-templates.

Grüße
Thomas