You are not logged in.

  • Login

t3kkn0kr4t

Unregistered

1

Friday, July 13th 2007, 6:39pm

XSLT Funktion für Anzahl Nodes

Hallo,
ich arbeite mit xslt und brauche eure Hilfe bei einem Problem!

Folgende xml Datei wird untersucht:

XML Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0"? encoding="UTF-8">
<root>
	<scroll>
		<column>
			<row>
				<image></image>
			</row>
			<row>
				<content></content>
			</row>
		</column>
		<column>
			<row>
				<image></image>
			</row>
			<row>
				<content></content>
			</row>
			<row>
				<image></image>
			</row>
		</column>
		<column>
			<row>
				<image></image>
			</row>
			<row>
				<image></image>
			</row>
			<row>
				<content></content>
			</row>
		</column>
         </scroll>  
</root>


Ich möchte mich an beliebiger Stelle im xml im node "row" befinden und bestimmen können, wie hoch die Anzahl nodes "row" pro Elternnode column maximal sein wird und wie hoch sie im nächstfolgenden Nachbarelement ist.
Am besten wäre es im template von row kann aber auch ausserhalb sein falls notwendig. Das führt mich dann zur 2.Frage wie ich den ermittelten Wert in andere <xsl:templates> übergeben bzw. ob globales Zugreifen auf die Variable möglich ist.

meine bisherigen versuche zum testen ob der rückgabe wert wenigstens eine sinnvolle zahl enthält geben mir immer nur 0 zurück.

:shock:

XML Code

1
2
3
<xslt:apply-templates select="row">
               <xsl:value-of select="count(parent::column/following-sibling::child::row)"/>            
</xslt:apply-templates>


EDIT: sehe grad Formatierung entfernt die Absätze ich hoff es ist trotzdem lesbar
//EDIT by d0nut: Syntax Highlighting geadded

2

Friday, July 13th 2007, 8:30pm

Wenn ich das richtig verstehe, klingt das ziemlich strange.... Dann solltest du dir besser nochmal Gedanken über die Struktur machen. Warum soll denn jeder einzelne Node seinem Parent mitteilen können wie es sich zu verhalten hat.
Das einzusetzen hat doch sowieso nur 1x Sinn und dann könntest du es ja auch ins Eltern-Element stecken.

Habe ich es überhaupt richtig verstanden.

Du definierst in irgendeinem Node ein Limit...

XML Code

1
2
3
4
5
6
<root>
        <scroll>
                <column>
                        <row>
                                <image limit="5"></image>
                        </row>


Und nun darf es über image (also in row) nur maximal 4 weitere row Einträge geben?

t3kkn0kr4t

Unregistered

3

Sunday, July 15th 2007, 1:31pm

Hi,

sorry aber wahrscheinlich habe ich meine Frage zu komplex formuliert.
Ich versuche immer soviel Information wie möglich einzubauen so dass es manchmal unübersichtlich wird.

Zur Struktur: die ist so vorgegeben und lässt sich leider nicht mehr ändern.

Zu dem Problem: ich möchte aus den nodes columns / row eine HTML table bauen.
"column" entspricht "tr", "row" entspricht td (-> whyever)
Da die 1. column meist! (nicht immer) nur die Überschrift ( + zus. Grafik) enthält will ich prüfen wieviel td in der 1. tr generiert werden und dies mit der max. anzahl td im dokument vergleichen und ggf (if first < max) ein colspan setzen damit die allgemein Tabellenformatierung erhalten bleibt.

Ich hoffe damit ist das Problem besser zu verstehen.

4

Sunday, July 15th 2007, 4:49pm

Mit einem konkreten Problem macht das doch viel mehr Sinn ;-)

Am besten du suchst dir erstmal das Maxmimum an Spalten:

XML Code

1
2
3
4
5
6
7
8
<xsl:variable name="maximum">
	<xsl:for-each select="//scroll/column">
		<xsl:sort select="count(row)" order="descending" />
		<xsl:if test="position()=1">
			<xsl:value-of select="count(row)" />
		</xsl:if>
	</xsl:for-each>
</xsl:variable>


Wenn du das vorher weißt, kannst du dann die Überprüfung jeweils an letzter Position machen und dort ein colspan einfügen:

XML Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<xsl:element name="table">
	<xsl:attribute name="border">1</xsl:attribute>
	<xsl:for-each select="//scroll/column">
		<xsl:element name="tr">
			<xsl:for-each select="row">
				<xsl:element name="td">
					<xsl:value-of select="." />
					<xsl:if test="position()=last()">
						<xsl:if test="position() &lt; $maximum">
							<xsl:attribute name="colspan">2</xsl:attribute>
						</xsl:if>
					</xsl:if>
				</xsl:element>
			</xsl:for-each>
		</xsl:element>
	</xsl:for-each>
</xsl:element>


Auch wenn die Bedingung trifft.. irgendwie hat der colspan keine Auswirkungen... es ist aber sehr, sehr nahe an der Lösung.

t3kkn0kr4t

Unregistered

5

Monday, July 16th 2007, 8:12pm

wow,

ersten mal Vielen Dank für das template zum rausfinden der Maximal Zellenanzahl.

Das kann ich gut gebrauchen. Ich hab nach einigem hin und her mal deinen code 1:1 in mein xsl eingebaut.

Das eine neue table erzeugt wird kommt mir erstmal ganz recht.

Ich bekomm jetzt aber immer folgende fehlermeldung:


Quoted

Warning: process() [function.process]: runtime error: file xslt/NaviDaten.xsl line 163 element attribute in /mnt/workspace/xslt-test/trunk/index_html.php on line 135

Warning: process() [function.process]: xsl:attribute: Cannot add attributes to an element if children have been already added to the element. in /mnt/workspace/xslt-test/trunk/index_html.php on line 135



hab das ganze in einem template name="test" was einfach per call-template aufgerufen wird hatte element name="table" direkt mit table ersetzt da ich dachte es würde einen unterschied machen...

XML Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<xsl:template name="test">
        <xsl:variable name="maximum">
            <xsl:for-each select="//scroll/column">
                <xsl:sort select="count(row)" order="descending" />
                <xsl:if test="position()=1">
                    <xsl:value-of select="count(row)" />
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
            <table cellpadding="0" cellspacing="0" border="1">        
                <xsl:for-each select="//scroll/column">
                    <xsl:element name="tr">
                        <xsl:for-each select="row">
                            <xsl:element name="td">
                                <xsl:value-of select="." />
                                <xsl:if test="position()=last()">
                                    <xsl:if test="position() &lt; $maximum">
                                        <xsl:attribute name="colspan">2</xsl:attribute> -> Zeile 163
                                    </xsl:if>
                                </xsl:if>
                            </xsl:element>
                        </xsl:for-each>
                    </xsl:element>
                </xsl:for-each>
            </table>
 
 
    </xsl:template>

6

Monday, July 16th 2007, 8:59pm

Quoted

Warning: process() [function.process]: xsl:attribute: Cannot add attributes to an element if children have been already added to the element

ich teste derzeit nur mit dem Firefox (Keine Fehlertexte). Die Fehlermeldung erklärts..

Das <xsl:value-of select="." /> darf erst nach der colspan Definition aufgerufen werden.

XML Code

1
2
3
4
5
6
7
8
<xsl:element name="td">
	<xsl:if test="position()=last()">
		<xsl:if test="position() &lt; $maximum">
			<xsl:attribute name="colspan"><xsl:value-of select="$maximum - position() + 1"/></xsl:attribute>
		</xsl:if>
	</xsl:if>
	<xsl:value-of select="." />
</xsl:element>


Und schon klappt der Code. Habe auch gleich die Berechnung des colspans eingefügt ;-)

t3kkn0kr4t

Unregistered

7

Wednesday, July 18th 2007, 9:35pm

Vielen Dank für den code.
Hab sonst immer nur mit apply-templates gearbeitet.
Foreach werd jetzt in Zukunft mehr benutzen ist wesentlich kompakter zu halten.

Die Tabelle wird jetzt astrein formatiert :D
Ich werd jetzt erstmal mit css bzw. div blöcken für die Darstellung experimentieren da ich noch einige andere Formatierungen wie Abstand zwischen 2 colnode by bedingung following::row/@type=fmt_headline_2 und x,y,width,height pro column/row einbauen muss.

Similar threads

Social bookmarks