[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

tree conversion

hans

10/19/2015 3:02:00 AM

This is s-xml output of an xml file

'(:|bookstore|
((:|book| :|category| "cooking")
((:|title| :|lang| "en")
"Everyday Italian")
(:|author|
"Giada De Laurentiis")
(:|year|
"2005")
(:|price|
"30.00"))
((:|book| :|category| "children")
((:|title| :|lang| "en")
"Harry Potter")
(:|author|
"J K. Rowling"))))

I am struggling contructing a recursive function
converting the above into tis tree

'("bookstore"
("book (category cooking)"
("title (lang en)"
("Everyday Italian"))
("author"
("Giada De Laurentiis"))
("year"
("2005"))
("price"
("30.00")))
("book (category children)"
("title (lang en)"
("Harry Potter"))
("author"
("J K. Rowling"))))

Could you please show how one would systematically do this?

Thank you very much
Hans
4 Answers

Pascal J. Bourguignon

10/19/2015 4:26:00 AM

0

schatzer.johann@gmail.com writes:

> This is s-xml output of an xml file
>
> '(:|bookstore|
> ((:|book| :|category| "cooking")
> ((:|title| :|lang| "en")
> "Everyday Italian")
> (:|author|
> "Giada De Laurentiis")
> (:|year|
> "2005")
> (:|price|
> "30.00"))
> ((:|book| :|category| "children")
> ((:|title| :|lang| "en")
> "Harry Potter")
> (:|author|
> "J K. Rowling"))))
>
> I am struggling contructing a recursive function
> converting the above into tis tree
>
> '("bookstore"
> ("book (category cooking)"
> ("title (lang en)"
> ("Everyday Italian"))
> ("author"
> ("Giada De Laurentiis"))
> ("year"
> ("2005"))
> ("price"
> ("30.00")))
> ("book (category children)"
> ("title (lang en)"
> ("Harry Potter"))
> ("author"
> ("J K. Rowling"))))
>
> Could you please show how one would systematically do this?

Go read:
http://groups.google.com/group/comp.lang.lisp/msg/0c66e5...
http://groups.google.com/group/comp.lang.lisp/msg/40efa5...

--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Kaz Kylheku

10/19/2015 5:42:00 AM

0

On 2015-10-19, schatzer.johann@gmail.com <schatzer.johann@gmail.com> wrote:
> This is s-xml output of an xml file
>
> '(:|bookstore|
> ((:|book| :|category| "cooking")
> ((:|title| :|lang| "en")
> "Everyday Italian")
> (:|author|
> "Giada De Laurentiis")
> (:|year|
> "2005")
> (:|price|
> "30.00"))
> ((:|book| :|category| "children")
> ((:|title| :|lang| "en")
> "Harry Potter")
> (:|author|
> "J K. Rowling"))))
>
> I am struggling contructing a recursive function
> converting the above into tis tree
>
> '("bookstore"
> ("book (category cooking)"
> ("title (lang en)"
> ("Everyday Italian"))
> ("author"
> ("Giada De Laurentiis"))
> ("year"
> ("2005"))
> ("price"
> ("30.00")))
> ("book (category children)"
> ("title (lang en)"
> ("Harry Potter"))
> ("author"
> ("J K. Rowling"))))
>
> Could you please show how one would systematically do this?

Systematically, we begin by specifying the rewrite rules, and
assuring ourselves that the specification is right.

Let us denote the basic transformation with curly braces { }
and a transformation applies individually to the elements of
a list using *{ }:

From the example, it seems we have two main cases:

{ (:|symbol| rest...) } -> ("symbol" *{ rest... })

{ ((:|symbol| attributes ...) rest...) ("symbol (attributes ...)" *{ rest ...})

For completeness, we can probably add:

{ () } -> ()

Now these rest... items can just be strings, so we have
to treat those:

{ "str" } -> "str"

We need to know how to generate these strings. The symbol :|abc| can be
converted to "abc" via the symbol-name function, or more generally
via princ-to-string. The latter handles the attribute lists also,
but we have to massage their shape. An even better idea is to use
the format function:

(format nil "~a" :|foo|) -> "foo"

(format nil "~a ~a" :|foo| '(:|bar| :|xyzzy|)) -> "foo (bar xyzzy)"

So now we have the ingredients:

(defun transform (sxml)
(cond
((null sxml) nil)
((atom sxml) ;; implies stringp
(format nil "~a" sxml))
((symbolp (car sxml))
(destructuring-bind (sym . rest) sxml
`(,(format nil "~a" sym)
,@(mapcar #'transform rest))))
(t (destructuring-bind ((sym . rest-attrs) . rest) sxml
`(,(format nil "~a ~a" sym rest-attrs)
,@(mapcar #'transform rest))))))


Test:

(transform '(:|bookstore|
((:|book| :|category| "cooking")
((:|title| :|lang| "en")
"Everyday Italian")
(:|author|
"Giada De Laurentiis")
(:|year|
"2005")
(:|price|
"30.00"))
((:|book| :|category| "children")
((:|title| :|lang| "en")
"Harry Potter")
(:|author|
"J K. Rowling")))))

-->

("bookstore"
("book (category cooking)" ("title (lang en)" "Everyday Italian")
("author" "Giada De Laurentiis") ("year" "2005") ("price" "30.00"))
("book (category children)" ("title (lang en)" "Harry Potter")
("author" "J K. Rowling")))

Oops, not quite. We are missing the rule for wrapping the element
contents in an extra list layer. It seems that a hack for achieving
this is to wrap an extra list around string items:

(defun transform (sxml)
(cond
((null sxml) nil)
((atom sxml) ;; implies stringp
(list (format nil "~a" sxml)))
((symbolp (car sxml))
(destructuring-bind (sym . rest) sxml
`(,(format nil "~a" sym)
,@(mapcar #'transform rest))))
(t (destructuring-bind ((sym . rest-attrs) . rest) sxml
`(,(format nil "~a ~a" sym rest-attrs)
,@(mapcar #'transform rest))))))

I now get:

("bookstore"
("book (category cooking)" ("title (lang en)" ("Everyday Italian"))
("author" ("Giada De Laurentiis")) ("year" ("2005")) ("price" ("30.00")))
("book (category children)" ("title (lang en)" ("Harry Potter"))
("author" ("J K. Rowling"))))

William James

10/19/2015 9:55:00 AM

0

Kaz Kylheku wrote:

> On 2015-10-19, schatzer.johann@gmail.com <schatzer.johann@gmail.com> wrote:
> > This is s-xml output of an xml file
> >
> > '(:|bookstore|
> > ((:|book| :|category| "cooking")
> > ((:|title| :|lang| "en")
> > "Everyday Italian")
> > (:|author|
> > "Giada De Laurentiis")
> > (:|year|
> > "2005")
> > (:|price|
> > "30.00"))
> > ((:|book| :|category| "children")
> > ((:|title| :|lang| "en")
> > "Harry Potter")
> > (:|author|
> > "J K. Rowling"))))
> >
> > I am struggling contructing a recursive function
> > converting the above into tis tree
> >
> > '("bookstore"
> > ("book (category cooking)"
> > ("title (lang en)"
> > ("Everyday Italian"))
> > ("author"
> > ("Giada De Laurentiis"))
> > ("year"
> > ("2005"))
> > ("price"
> > ("30.00")))
> > ("book (category children)"
> > ("title (lang en)"
> > ("Harry Potter"))
> > ("author"
> > ("J K. Rowling"))))
> >
> > Could you please show how one would systematically do this?
>
> Systematically, we begin by specifying the rewrite rules, and
> assuring ourselves that the specification is right.
>
> Let us denote the basic transformation with curly braces { }
> and a transformation applies individually to the elements of
> a list using *{ }:
>
> From the example, it seems we have two main cases:
>
> { (:|symbol| rest...) } -> ("symbol" *{ rest... })
>
> { ((:|symbol| attributes ...) rest...) ("symbol (attributes ...)" *{ rest ...})
>
> For completeness, we can probably add:
>
> { () } -> ()
>
> Now these rest... items can just be strings, so we have
> to treat those:
>
> { "str" } -> "str"
>
> We need to know how to generate these strings. The symbol :|abc| can be
> converted to "abc" via the symbol-name function, or more generally
> via princ-to-string. The latter handles the attribute lists also,
> but we have to massage their shape. An even better idea is to use
> the format function:
>
> (format nil "~a" :|foo|) -> "foo"
>
> (format nil "~a ~a" :|foo| '(:|bar| :|xyzzy|)) -> "foo (bar xyzzy)"
>
> So now we have the ingredients:
>
> (defun transform (sxml)
> (cond
> ((null sxml) nil)
> ((atom sxml) ;; implies stringp
> (format nil "~a" sxml))
> ((symbolp (car sxml))
> (destructuring-bind (sym . rest) sxml
> `(,(format nil "~a" sym)
> ,@(mapcar #'transform rest))))
> (t (destructuring-bind ((sym . rest-attrs) . rest) sxml
> `(,(format nil "~a ~a" sym rest-attrs)
> ,@(mapcar #'transform rest))))))
>
>
> Test:
>
> (transform '(:|bookstore|
> ((:|book| :|category| "cooking")
> ((:|title| :|lang| "en")
> "Everyday Italian")
> (:|author|
> "Giada De Laurentiis")
> (:|year|
> "2005")
> (:|price|
> "30.00"))
> ((:|book| :|category| "children")
> ((:|title| :|lang| "en")
> "Harry Potter")
> (:|author|
> "J K. Rowling")))))
>
> -->
>
> ("bookstore"
> ("book (category cooking)" ("title (lang en)" "Everyday Italian")
> ("author" "Giada De Laurentiis") ("year" "2005") ("price" "30.00"))
> ("book (category children)" ("title (lang en)" "Harry Potter")
> ("author" "J K. Rowling")))
>
> Oops, not quite. We are missing the rule for wrapping the element
> contents in an extra list layer. It seems that a hack for achieving
> this is to wrap an extra list around string items:
>
> (defun transform (sxml)
> (cond
> ((null sxml) nil)
> ((atom sxml) ;; implies stringp
> (list (format nil "~a" sxml)))
> ((symbolp (car sxml))
> (destructuring-bind (sym . rest) sxml
> `(,(format nil "~a" sym)
> ,@(mapcar #'transform rest))))
> (t (destructuring-bind ((sym . rest-attrs) . rest) sxml
> `(,(format nil "~a ~a" sym rest-attrs)
> ,@(mapcar #'transform rest))))))
>
> I now get:
>
> ("bookstore"
> ("book (category cooking)" ("title (lang en)" ("Everyday Italian"))
> ("author" ("Giada De Laurentiis")) ("year" ("2005")) ("price" ("30.00")))
> ("book (category children)" ("title (lang en)" ("Harry Potter"))
> ("author" ("J K. Rowling"))))


Gauche Scheme:

(use util.match)

(define (parse stuff)
(match stuff
[(? string? s) (list s)]
[(? keyword? k) (x->string k)]
[((? keyword? k1) (? keyword? k2) (? string? s)) #"~k1 (~k2 ~s)"]
[xs (map parse xs)]))

(parse
'(:|bookstore|
((:|book| :|category| "cooking")
((:|title| :|lang| "en") "Everyday Italian")
(:|author| "Giada De Laurentiis")
(:|year| "2005")
(:|price| "30.00")
)
((:|book| :|category| "children")
((:|title| :|lang| "en")
"Harry Potter")
(:|author|
"J. K. Rowling"))))

("bookstore"
("book (category cooking)"
("title (lang en)" ("Everyday Italian"))
("author" ("Giada De Laurentiis"))
("year" ("2005"))
("price" ("30.00")))
("book (category children)"
("title (lang en)" ("Harry Potter"))
("author" ("J. K. Rowling"))))

--
It is extremely gratifying to ... achieve membership in an elite that is going
to make history.... The only drawback is that the self-appointed shepherds are
likely to find eventually that they were only sheepdogs and herded the flock
toward a destination of which they knew nothing. --- R. P. Oliver

William James

10/19/2015 1:27:00 PM

0

WJ wrote:

> Gauche Scheme:
>
> (use util.match)
>
> (define (parse stuff)
> (match stuff
> [(? string? s) (list s)]
> [(? keyword? k) (x->string k)]
> [((? keyword? k1) (? keyword? k2) (? string? s)) #"~k1 (~k2 ~s)"]
> [xs (map parse xs)]))

Without using pattern-matching:

(define (parse stuff)
(cond
[(string? stuff) (list stuff)]
[(keyword? stuff) (x->string stuff)]
[(and (= 3 (length stuff))
(every (cut <> <>)
(list keyword? keyword? string?)
stuff))
(apply format "~a (~a ~a)" stuff)]
[else (map parse stuff)]))