Anzahl der Zellen mit xPath

Alaniak

Erfahrenes Mitglied
Hallo zusammen,

ich häng schon seit einiger Zeit an einem Problem:
Und zwar lese ich Daten aus einer XML aus und schreibe die in eine Tabelle. Die XML hat eine beliebige Anzahl an Knoten.
Ich möchte in der Tabelle pro Zeile 4 Knoten ausgeben und dann kommt die nächste Zeile mit 4 ... usw.

Allerdings klappt das überhaupt nicht. Ich habe ungefähr diesen Aufbau:
PHP:
 <table>
   <x:forEach select="knoten">
      <x:if ... >
           <tr>
      </x:if>
      <td>knoten</td>
      <x:if ... >
           </tr>
      </x:if>
   </x:forEach>
</table>
Also wenn es sich um den 4. Knoten handelt (und auch nach dem letzten) kommt eine neue Zeile.

Hat da vielleicht jemand ne Idee.
 
Der Auszug den ich da stehen habe ist auch nur extrem abstrahiert. Bis auf die Tatsache, dass es nicht 4 Zellen pro Zeile sind klappt das ganze einwandfrei.
Hier mal ein Auszug aus der XML:

PHP:
<contact>
      <name></name>
      <street></street>
      <street-number></street-number>
      <city></city>
      <country></country>
      <phone></phone>
      <fax></fax>
      <email></email>
</contact>
.
.
.

Es gibt dann eine beliebige Anzahl von "contact". Pro Zelle ein "contact".
 
Also erstens ist das was Du machst XSLT und nicht XPATH. Du versuchst wie in PHP zu programmieren. Das wird nix. Dann kannst Du ja gleich PHP nehmen.

Dies ist meine Lösung

XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
	<contact>
	      <name>Mein Name</name>
	      <street>Strasse</street>
	      <street-number>19</street-number>
	      <city>Frankfurt</city>
	      <country>Germany</country>
	      <phone>123354</phone>
	      <fax>23456</fax>
	      <email>bla@blubb</email>
	</contact>
	<contact>
	      <name>bla</name>
	      <street>bla</street>
	      <street-number>bla</street-number>
	      <city>bla</city>
	      <country>bla</country>
	      <phone>bla</phone>
	      <fax>bla</fax>
	      <email>bla</email>
	</contact>
	<contact>
	      <name>bla</name>
	      <street>bla</street>
	      <street-number>bla</street-number>
	      <city>bla</city>
	      <country>bla</country>
	      <phone>bla</phone>
	      <fax>bla</fax>
	      <email>bla</email>
	</contact>
</root>

das XSLT-File dazu:

XML:
<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
	<xsl:output method="html" />
		
	<!-- Einsprungpunkt der Verarbeitung  -->
	<xsl:template match="/">
		<html>
			<body>
				<xsl:apply-templates />
			</body>
		</html>
	</xsl:template>
	
	<!-- tabelle für den Rootknoten -->
	<xsl:template match="root">
		<table border="1">
				<xsl:apply-templates />
		</table>
	</xsl:template>

	<!-- zeile für den Contactknoten -->
	<xsl:template match="contact">
		<tr>
			<!-- Ausgabe nur Spalten name + email --> 
		 	<xsl:apply-templates select="name|email"/>
			
			<!-- Ausgabe aller Spalten (auskommentiert) --> 
			<!--xsl:apply-templates /-->
			
		</tr>
	</xsl:template>

	<!-- spalte für alle Kinder von Contact -->
	<xsl:template match="contact/*">
		<tr>
		 	<xsl:value-of select="." />
		</tr>
	</xsl:template>

	
</xsl:stylesheet>

..und der Output

XML:
html>
   <body>
      <table border="1">
         	
         <tr>
            <tr>Mein Name</tr>
            <tr>bla@blubb</tr>
         </tr>
         	
         <tr>
            <tr>bla</tr>
            <tr>bla</tr>
         </tr>
         	
         <tr>
            <tr>bla</tr>
            <tr>bla</tr>
         </tr>
         
      </table>
   </body>
</html>

EDIT: Leute vergesst doch mal den ganzen Schleifenquatsch in XSLT. Der Code wird kompliziert, ist nicht in Archive auslagerbar. Nicht so robust gegen strukturelle Änderungen. Nicht wartbar und, und ....
 
Zuletzt bearbeitet von einem Moderator:
ich glaube ich habe Dich falsch verstanden. Du willst nur die ersten 4 Kontakte ausgeben, oder?

Das geht so:

XML:
<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
	<xsl:output method="html" />
		
	<!-- Einsprungpunkt der Verarbeitung  -->
	<xsl:template match="/">
		<html>
			<body>
				<xsl:apply-templates />
			</body>
		</html>
	</xsl:template>
	
	<!-- tabelle für den Rootknoten -->
	<xsl:template match="root">
		<table border="1">
				<xsl:apply-templates />
		</table>
	</xsl:template>

	<!-- zeile für den Contactknoten -->
	<xsl:template match="contact">
		<tr>

			<!-- Ausgabe aller Spalten lt steht für less Than und ist ein Kleinerzeichen  --> 
			<xsl:apply-templates select="*[position() &lt; 5]"/>
			
		</tr>
	</xsl:template>

	<!-- spalte für alle Kinder von Contact -->
	<xsl:template match="contact/*">
		<tr>
		 	<xsl:value-of select="." />
		</tr>
	</xsl:template>

	
</xsl:stylesheet>

EDIT: ich meine natürlich die ersten 4 Kinder von Kontakt....
 
Zuletzt bearbeitet von einem Moderator:
Nicht ganz. Die ersten 4 auszugeben ist nicht das Problem, sonder jeweils 4 in einer Zeile. Also die ersten 4, neue Zeile die nächsten 4, neue Zeile die nächsten 4 ... usw. eine beliebig lange Tabelle mit 4 Spalten und X Zeilen.
 
Meist Du das?

XML:
<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
	<xsl:output method="html" />
	<xsl:strip-space elements="*" />	
	<!-- Einsprungpunkt der Verarbeitung  -->
	<xsl:template match="/">
		<html>
			<body>
				<xsl:apply-templates />
			</body>
		</html>
	</xsl:template>
	
	<!-- tabelle für den Rootknoten -->
	<xsl:template match="root">
		<table border="1">
				<xsl:apply-templates />
		</table>
	</xsl:template>

	<!-- zeile für den Contactknoten -->
	<xsl:template match="contact">
		<xsl:call-template name="ersteVier">
			<xsl:with-param name="liste" select="*" />
		</xsl:call-template>	
	</xsl:template>

	<!-- spalte für alle Kinder von Contact -->
	<xsl:template match="contact/*">
		<td>
		 	<xsl:value-of select="." />
		</td>
	</xsl:template>
	
	<xsl:template name="ersteVier">
		<xsl:param name="liste" />
		<xsl:if test="$liste">
			<tr>
				<xsl:apply-templates select="$liste[position() &lt; 5]" />
			</tr>
			<xsl:call-template name="ersteVier">
				<xsl:with-param name="liste" select="$liste[position() &gt;= 5]" />
			</xsl:call-template>
		</xsl:if>
	
	</xsl:template>

	
</xsl:stylesheet>

EDIT: Das wäre die Ausgabe..

XML:
<html>
   <body>
      <table border="1">
         <tr>
            <td>Mein Name</td>
            <td>Strasse</td>
            <td>19</td>
            <td>Frankfurt</td>
         </tr>
         <tr>
            <td>Germany</td>
            <td>123354</td>
            <td>23456</td>
            <td>bla@blubb</td>
         </tr>
         <tr>
            <td>bla</td>
            <td>bla</td>
            <td>bla</td>
            <td>bla</td>
         </tr>
         <tr>
            <td>bla</td>
            <td>bla</td>
            <td>bla</td>
            <td>bla</td>
         </tr>
         <tr>
            <td>bla</td>
            <td>bla</td>
            <td>bla</td>
            <td>bla</td>
         </tr>
         <tr>
            <td>bla</td>
            <td>bla</td>
            <td>bla</td>
            <td>bla</td>
         </tr>
      </table>
   </body>
</html>
 
Zuletzt bearbeitet von einem Moderator:
Habs jetzt ein bisschen einfacher über eine Statusvariable und einer Modulo-Operation gelöst. Trotzdem vielen Dank.
 
XML:
<x:forEach varStatus="counter" var="contacttable" select="$contact">
	<c:if test="${counter.index mod 4 == 0}">
		<tr>
	</c:if>
	<td></td>				
	<c:if test="${counter.count mod 4 == 0 or counter.last}">
		</tr>
	</c:if>
</x:forEach>

Klappt 1A.
 
Zuletzt bearbeitet von einem Moderator:
Zurück