[plt-scheme] getting data out of xexpr's (xml)

From: Matt Jadud (jadudm at gmail.com)
Date: Wed Jan 2 19:30:44 EST 2008

A brute-force approach with match would look roughly like the code
below; note that I have the flu right now, and also have no idea where
some of your resulting data comes from (it appears by magic in your
alist example).

Cheers,
Matt

(define data
  '(graphml
    ((xmlns "http://graphml.graphdrawing.org/xmlns"))
    (graph
     ((edgedefault "undirected"))
     (key ((attr.name "name") (attr.type "string") (for "node") (id "name")))
     (key ((attr.name "gender") (attr.type "string") (for "node") (id
"gender")))
     (node ((id "1"))  (data ((key "name")) "Jeff")  (data ((key
"gender")) "M") )
     (node ((id "2"))  (data ((key "name")) "Ed")  (data ((key "gender")) "M") )
     (node ((id "3"))  (data ((key "name")) "Christiaan")  (data ((key

"gender")) "M") )
     (edge ((source "21") (target "126")))
     (edge ((source "21") (target "127")))
     (edge ((source "21") (target "128")))
     (edge ((source "21") (target "129")))
     )
    ))

(require (lib "plt-match.ss")
         (lib "list.ss"))

(define-struct edge (source target))
(define-struct node (id name gender))

(define (parse s)
  (match s
    [`(graphml ,_ ,graph)
      (parse graph)]
    [`(graph ,_ ,elements ...) ;; I used the ,_ to say "something is
here, but I don't care what it is"
     (filter (lambda (s)
               (or (edge? s) (node? s))) (map parse elements))]
    [`(key ,_ ...) (void)] ;; I don't know what to do with (key ...) elements.
    [`(node ((id ,id)) (data ((key "name")) ,name) (data ((key "gender")) ,g))
     (make-node id name g)]
    [`(edge ((source ,s) (target ,t)))
     (make-edge s t)]))

You may be able to use xquery or some other libraries to do this in
more elegant ways; this is a brute-force approach that might get you
close.

Cheers,
Matt

On Jan 2, 2008 7:02 PM, Robby Findler <robby at cs.uchicago.edu> wrote:
> Oh, I see. Yes, match is probably the right thing (using the
> quasiquote patterns). There may be a planet library for doing what you
> want more directly, I don't know. But assuming not, match.ss.
>
> Robby
>
>
> On Jan 2, 2008 5:55 PM, Stephen De Gabrielle <stephen at degabrielle.name> wrote:
> > Thanks for the quick response;
> >
> > My trouble isn't geting the xml into xexper, but turning xexpr into
> > key/value pairs.
> >
> > I do this;
> >
> >                                                       (xml->xexpr
> >
> > ((eliminate-whitespace '(graphml graph node edge) (lambda (x) x))
> >
> > (document-element (read-xml input-port))))
> >
> > Which gets much the same output as this
> >
> > (require (lib "xml.ss" "xml"))
> > (xml->xexpr (read-xml/element (open-input-string "
> > <graphml xmlns='http://graphml.graphdrawing.org/xmlns'>
> > <!-- metadata -->
> > <graph edgedefault='undirected'>
> >
> > <key id='name' for='node' attr.name='name' attr.type='string'/>
> > <key id='gender' for='node' attr.name='gender' attr.type='string'/>
> >
> > <!-- data -->
> > <node id='1'>
> >  <data key='name'>Jeff</data>
> >  <data key='gender'>M</data>
> >  </node>
> > <node id='2'>
> >  <data key='name'>Ed</data>
> >  <data key='gender'>M</data>
> > </node>
> > <node id='3'>
> >  <data key='name'>Christiaan</data>
> >  <data key='gender'>M</data>
> > </node>
> >
> > <edge source='2' target='1'></edge>
> > <edge source='3' target='3'></edge>
> > <edge source='1' target='2'></edge>
> >
> > </graph>
> > </graphml>")))
> >
> > which gives approximately;
> >
> > (graphml
> >   ((xmlns "http://graphml.graphdrawing.org/xmlns"))
> >   (graph
> >    ((edgedefault "undirected"))
> >    (key ((attr.name "name") (attr.type "string") (for "node") (id "name")))
> >    (key ((attr.name "gender") (attr.type "string") (for "node") (id "gender")))
> >    (node ((id "1"))  (data ((key "name")) "Jeff")  (data ((key "gender")) "M") )
> >    (node ((id "2"))  (data ((key "name")) "Ed")  (data ((key "gender")) "M") )
> >    (node ((id "3"))  (data ((key "name")) "Christiaan")  (data ((key
> > "gender")) "M") )
> >    (edge ((source "21") (target "126")))
> >    (edge ((source "21") (target "127")))
> >    (edge ((source "21") (target "128")))
> >    (edge ((source "21") (target "129")))
> >    )
> >   )
> >
> >
> > I'd like to use something like a regular expression, perhaps?
> >   /(node ((id $1))  (data ((key $2)) $3)/((class node) (id $1) ($2 $3) ($4 $5))/
> >
> > to get  a series of alists [1];
> >
> > ((class "graph-metadata") (dir #f))
> > ((class "node") (id "1") ("name" "Jeff")  ("gender" "M"))
> > ((class "node") (id "2") ("name" "Ed")  ("gender" "M"))
> > ((class "node") (id "3") ("name" "Christiaan") ("gender" "M"))
> > ((class "edge") (source "21") (target "126") (dir #f))
> > ((class "edge") (source "21") (target "127") (dir #f))
> > ((class "edge") (source "21") (target "128") (dir #f))
> > ((class "edge") (source "21") (target "129") (dir #f))
> >
> > Does this make more sense? It's turning the xexpr into key/value pairs
> > without making a labrinthine mess of for-each/map and caddr etc. like
> > in my original code that I need to work out. match.ss seems to be
> > about macros, so I'm not sure I'm on the right path.
> >
> > Thanks,
> >
> > Stephen
> >
> >
> > [1]Which I will process to add derived fields to ;
> > eg  ((class "node") (id "1") ("name" "Jeff")  ("gender" "M")  (x-pos
> > 43) (y-pos 34) (colour "Blue"))
> > (then finally turn into snips)
> >
> >
> >
> >
> >
> > On Jan 2, 2008 10:54 PM, Robby Findler <robby at cs.uchicago.edu> wrote:
> > > I think you want:
> > >
> > > (require (lib "xml.ss" "xml"))
> > > (xml->xexpr (read-xml/element (open-input-string "<a><b>cdef</b></a>")))
> > >
> > > which produces
> > >
> > > '(a () (b () "cdef"))
> > >
> > > hth,
> > > Robby
> > >
> > >
> > > On Jan 2, 2008 4:51 PM, Stephen De Gabrielle <stephen at degabrielle.name> wrote:
> > > > Hi,
> > > >
> > > > I'm using  (lib "xml.ss" "xml") to read some GraphML  into xexpr's
> > > >
> > > >
> > > > Once I have loaded it I'm using this sort of (non-working)thing  to
> > > > turn it from the xexpr into an alist using for-each and
> > > > caddr/cadr/car/cdr etc.
> > > >
> > > > ;; populate ;;
> > > >       (let* ((data (cdr (caddr xexpr-graph)))) ; get the graph part
> > > >         (for-each
> > > >          (lambda (row) ;; badly named local for node or edge tag.
> > > >            (if (equal? '(edgedefault "undirected") row) (set! edge-directed #t)
> > > >                (let* ((row-type (car row))
> > > >                       (row-Attributes (if (or (equal? row-type 'node)
> > > >                                                (equal? row-type
> > > > 'edge)) (get-row-Attributes row))))
> > > >                  (send alist-collection insert (append (list (list
> > > > 'class row-type)) (car row-Attributes) (cadr row-Attributes )))))) ;;
> > > > add an alist to the collection for each node or edge
> > > >          data))
> > > >
> > > >  (http://graphml.graphdrawing.org/ socialnet.xml example attached)
> > > >
> > > > My Question is - is there a better way of getting my nodes, edges and
> > > > [graph] metadata(directed/undirected) as what I am writing here is
> > > > hard to write, hard to read, and doesn't even work.
> > > >
> > > > Should I use  plt-match.ss or  match.ss instead?
> > > >
> > > > Can anyone suggest some code in 'PLT-Full' (v3.99.0.8) that I can
> > > > read. It doesn't have to be xml - just xexpr-like - and I am getting
> > > > getter at reading code, even without comments :)
> > > >
> > > >
> > > > Cheers,
> > > >
> > > > Stephen
> > > >
> > > >
> > > >
> > > > --
> > > > Stephen De Gabrielle
> > > > s.degabrielle at ucl.ac.uk
> > > > Telephone +44 (0)20 7679 5242 (x45242)
> > > > Mobile                  079 851 890 45
> > > > http://www.uclic.ucl.ac.uk/annb/MaSI.html
> > > > University College London Interaction Centre
> > > > Remax House - 31/32 Alfred Place
> > > > London - WC1E 7DP
> > > >
> > > > "There's an old story about the person who wished his computer were as
> > > > easy to use as his telephone.  That wish has come true, since I no
> > > > longer know how to use my telephone. " -- Bjarne Stroustrup
> > > >
> > > > _________________________________________________
> > > >   For list-related administrative tasks:
> > > >   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> > > >
> > > >
> > >
> >
> >
> >
> > --
> >
> >
> >
> >
> >
> > --
> > Stephen De Gabrielle
> > s.degabrielle at ucl.ac.uk
> > Telephone +44 (0)20 7679 5242 (x45242)
> > Mobile                  079 851 890 45
> > http://www.uclic.ucl.ac.uk/annb/MaSI.html
> > University College London Interaction Centre
> > Remax House - 31/32 Alfred Place
> > London - WC1E 7DP
> >
> > "There's an old story about the person who wished his computer were as
> > easy to use as his telephone.  That wish has come true, since I no
> > longer know how to use my telephone. " -- Bjarne Stroustrup
> >
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>


Posted on the users mailing list.