PHP Forum

PHP Forum (http://www.selfphp.de/forum/index.php)
-   MySQLi/PDO/(MySQL) (http://www.selfphp.de/forum/forumdisplay.php?f=22)
-   -   NESTED SETS in XML ausgeben (http://www.selfphp.de/forum/showthread.php?t=23668)

mr_sol 14.10.2010 19:31:20

NESTED SETS in XML ausgeben
 
Hallo

Vielleich hat jemand von euch eine Idee oder Hinweis.

Meine Datenstruktur (mysql) ist als Nested Sets abgebildet. Ich möchte diese als XML Baum ausgeben (kein PHP). Meine bisherigen Versuche scheitern am schliessen der Tags.

BEISPIEL-BAUM soll folgendes Ergebnis liefern:
Code:

A[01,16]
B[02,03]    C[04,13]    H[14,15]
            D[05,12]
            E[06,07]    F[08,11]
                        G[09,10]


Ergebnis:

<A>content A
<B>content B</B>
<C>content C
<D>content D
<E>content E</E>
<F>content F
<G>content G</G></F></D></C>
<H>content H</H></A>



Hier ein Test-CONTENT:
Code:

CREATE TABLE IF NOT EXISTS `tree` (
  `id` int(11) NOT NULL,
  `tag` varchar(100) NOT NULL,
  `lft` int(11) NOT NULL,
  `rgt` int(11) NOT NULL,
  `desc` text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


INSERT INTO `tree` (`id`, `tag`, `lft`, `rgt`, `desc`) VALUES
(1, 'A', 1, 16, 'content A'),
(2, 'B', 2, 3, 'content B'),
(3, 'C', 4, 13, 'content C'),
(4, 'D', 5, 12, 'content D'),
(5, 'E', 6, 7, 'content E'),
(6, 'F', 8, 11, 'content F'),
(7, 'G', 9, 10, 'content G'),
(8, 'H', 14, 15, 'content H');


Vielen Dank im voraus

thomas_w 14.10.2010 19:41:05

AW: NESTED SETS in XML ausgeben
 
Leider kenne ich mich mit XML zuwenig aus, als dass ich spontan dafür eine Lösung finde. Ich denke MySQL ist aber dafür noch nicht richtig ausgestattet:

Die MySQL-XML findet Du hier (ab MySQL 5.1.5 ):
http://dev.mysql.com/doc/refman/5.1/...functions.html

Andere Datenbank wie IBM DB2 oder ORACLE (die es beide auch als kostenlose Versionen gibt) können inzwischen besser mit XML umgehen. Hier was ausführliches für ORACLE:
http://download-uk.oracle.com/docs/c...9/xdb13gen.htm

EDIT ... noch was für MySQL
http://dev.mysql.com/tech-resources/...ql5.1-6.0.html
http://www.mysqludf.org/lib_mysqludf_xql/index.php


Grüße
Thomas

mr_sol 14.10.2010 23:25:47

AW: NESTED SETS in XML ausgeben
 
Vielen Dank für dein Bemühen. Leider ist nicht der Lösungsweg dabei. Der Nested Set ist super schnell um Bäume aufzubauen, leider klappt das schliessen der XML Tags nicht.

thomas_w 15.10.2010 00:02:41

AW: NESTED SETS in XML ausgeben
 
Schade, aber zeig doch mal wie Dein bisheriger SQL aussieht, dann fällt vielleicht noch jemand etwas ein und ich lerne was neues...

Grüße
Thomas

mr_sol 15.10.2010 08:37:54

AW: NESTED SETS in XML ausgeben
 
Ich habe 2 Lösungsansätze


Lösungsansatz 1:
Code:

SELECT n.*,               
concat('<',n.tag,'>',
n.desc,
IF(n.rgt-n.lft=1,
        group_concat(

       
                IF(
                p.rgt<n.rgt+4,
                concat('</',p.tag,'>'),
                '')
        ORDER BY p.rgt
SEPARATOR ''
        )
,'')
)
    FROM tree n,
        tree p
  WHERE n.lft BETWEEN p.lft AND p.rgt
GROUP BY n.id
ORDER BY n.lft

Erklärung:
p...parent Elemente mit einen lft,rgt Wert
n...node oder das aktuelle Elemente welches auch einen lft,rgt Wert besitzt, welche sich zwischen p.lft und p.rgt befindet
zB:

Element G[9,10] befindet sich innerhalb von A[1,16],C[4,13],D[5,12],F[8,11],G[9,10] - aus dieser Anzahl der Elemente kannst du die Tiefe des Baumes auf G bezogen erfahren.


Um zB Element G zu schliessen benötige ich </G></F></D></C> das Element </A> sollte sich nicht in der Menge gefinden.

mit p.rgt<n.rgt+4 habe ich die Menge beschränkt - nicht sehr sinnvoll.


http://www.klempert.de/nested_sets/
Gute Seite





Lösungsansatz 2: Die Menge mit einen JOIN einschränken.

Ich gehe von 2 Mengen aus:

Menge der Elemente ober aktuellen Element (siehe oben)
zB:G - G,F,D,C,A

Menge aller Elemente bei welcher der lft Wert grösser als der aktuelle lft und rgt Wert ist.
zB:G - H
schränke diese auf das erste Element ein (falls mehrere vorhanden sind)


Schränke erste Menge auf alle Elemente ein die kleiner als der lft Wert des Elemente H sind - G,F,D,C


http://www.developersdex.com/gurus/a...112.asp?Page=3
Die Seite des Nested Sets Meisters


Nur wie mache ich das am besten?

thomas_w 15.10.2010 10:18:37

AW: NESTED SETS in XML ausgeben
 
Zitat:

Zitat von mr_sol (Beitrag 138524)
http://www.developersdex.com/gurus/a...112.asp?Page=3
Die Seite des Nested Sets Meisters


Nur wie mache ich das am besten?

Interessanter Link, den kannte ich bisher nicht.

a) Ich denke, Du benötigt einen rekursiven SQL und der ist mit MySQL derzeit nicht möglich, soweit ich weiß. Eventuell läßt sich sowas mit einem Stored Procedure nachbauen.
b) Muss es unbedingt XML sein? Mit JSON gibt es ähnliche Möglichkeiten, allerdings bist Du dann bei PHP oder JavaScript

Rekursives SQL mit IBM DB2:
Code:

WITH common_table ( spaltenliste ) AS
( Ursprungsselect
UNION ALL
Rekursionsselect )
SELECT spaltenliste FROM common_table WHERE ...

http://www.mayeruli.de/db2/rekursives-sql.html
http://www.mayeruli.de/db2/nested-table.html

Nächste Woche habe ich wieder mehr Zeit dafür..bis dahin.

Grüße
Thomas

mr_sol 17.10.2010 11:53:26

AW: NESTED SETS in XML ausgeben
 
Hallo Thomas!

Danke für deine Rückmeldung. Erstaunlicherweise gibt für Nested Set viele Lösungen
(Blattsuch, Kindersuche, Levelhöhe, Nachfolger, Vorfahren,ect) nur dieses Thema findet man nicht.

Es gibt zwar ein Buch:
Book 8.3.2 [Page 195] - XML data management: native XML and XML-enabled database systems

http://books.google.com/books?id=7LN...page&q&f=false

wo das Nested Sets für XML verwendet wird.


Auch hier Lösungsansätze:
http://www.artfulsoftware.com/mysqlb...qled1ch20.html



1) Die Idee mit UNION finde ich gut, sollte mit mySQL 5.0 klappen stehe aber mit der Query an

2) Habe noch etwas probiert, auf Basis Menge beschneiden (Lösungsansatz 2).

Code:

SELECT node.tag,follower.tag,node.lft,follower.lft,node.rgt,follower.rgt
    FROM tree AS node,
        tree AS follower
 WHERE follower.rgt>=node.rgt
  AND follower.rgt<
      (SELECT MIN(s.lft) FROM tree AS s WHERE s.lft>node.rgt)
 ORDER BY node.lft,follower.rgt


Schneide Menge der Nachfolger an der Stelle wo erstesmal ein höhere lft Wert steht als
der aktuelle Knoten (node). Alles was sich zwischen den aktuellen node und kleiner als s.lft befindet bleibt erhalten.

zB:
G[9,10] -> Nachfolger F,D,C,H,A
Erster Wert wo lft grösser als G rgt -> H[14,15]
Restmenge ist daher -> F,D,C

Problem: es sollte eine Ausnahmeregel für A gebe...H wird nicht ausgegeben.




Leider kann ich nicht mit JSON arbeiten, da die Verarbeiten in XSLT erfolgt. MySQL ist für mein Projekt aus anderen Gründen sehr gut geeignet....
vielleicht klappts ja doch:)

grüsse helmut

thomas_w 17.10.2010 17:20:44

AW: NESTED SETS in XML ausgeben
 
So, mal eine erster Versuch zum Thema. Die Spalte "desc" würde ich umbenennen. Reservierte SQL-Worter als Spaltename zu verwenden, schafft nur unnötig Probleme.

Code:

SELECT CASE flag
        WHEN 1 THEN CONCAT( '<' , t.tag, '>', t.`desc` )
        WHEN 2 THEN CONCAT( '</' , t.tag, '>')
        END AS xml_teil
  FROM (SELECT tag, 1 AS flag, lft AS pt, id
          FROM tree
       
        UNION ALL
       
        SELECT tag, 2 AS flag, rgt AS pt, id
          FROM tree
       
        ORDER BY pt, tag ) r
  JOIN tree t
    ON t.id = r.id
ORDER BY r.pt, r.tag;

+--------------+
| xml_teil    |
+--------------+
| <A>content A |
| <B>content B |
| </B>        |
| <C>content C |
| <D>content D |
| <E>content E |
| </E>        |
| <F>content F |
| <G>content G |
| </G>        |
| </F>        |
| </D>        |
| </C>        |
| <H>content H |
| </H>        |
| </A>        |
+--------------+
16 rows in set (0.00 sec)

mysql>

Die einzelnen Ergebnis-Zeilen müssen dann noch in einen XML-String aneiander gehängt werden.

Mit XML kenne ich mich nicht besonders aus. Stimmt die "Richtung"?

Grüße
Thomas

mr_sol 17.10.2010 20:44:11

AW: NESTED SETS in XML ausgeben
 
Danke, genial einfach gelöst....ich denke zu kompliziert.


Die baust zwei Menge zusammen und weist lft bzw rgt pt zu. Die gesamte Menge wird nach pt sortiert. Aus der flag erkennst du ob <> oder </>. Der t dient zum Durchlaufen des Baumes.

Stimmt's?


Dürfte ich noch eine zusätzliche Frage stellen?

thomas_w 17.10.2010 21:07:10

AW: NESTED SETS in XML ausgeben
 
Danke für das Lob!
Genau, der SQL arbeitet so, wie Du es verstanden hast. Es war kein rekursives SQL nötig. Da hab ich zuerst zu kompliziert gedacht.

Natürlich kannst Du hier weitere Fragen stellen. Am Besten in einem neuen Thread, wenn es nicht direkt etwas mit dieser Frage zu tun hat.

Grüße
Thomas


Alle Zeitangaben in WEZ +2. Es ist jetzt 14:25:28 Uhr.

Powered by vBulletin® Version 3.8.3 (Deutsch)
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.