123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- ;;;; sxml.xpath.test -*- scheme -*-
- ;;;;
- ;;;; Copyright (C) 2010 Free Software Foundation, Inc.
- ;;;; Copyright (C) 2001,2002,2003,2004 Oleg Kiselyov <oleg at pobox dot com>
- ;;;;
- ;;;; This library is free software; you can redistribute it and/or
- ;;;; modify it under the terms of the GNU Lesser General Public
- ;;;; License as published by the Free Software Foundation; either
- ;;;; version 3 of the License, or (at your option) any later version.
- ;;;;
- ;;;; This library is distributed in the hope that it will be useful,
- ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ;;;; Lesser General Public License for more details.
- ;;;;
- ;;;; You should have received a copy of the GNU Lesser General Public
- ;;;; License along with this library; if not, write to the Free Software
- ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- ;;; Commentary:
- ;;
- ;; Unit tests for (sxml xpath).
- ;;
- ;;; Code:
- (define-module (test-suite sxml-xpath)
- #:use-module (test-suite lib)
- #:use-module (sxml xpath))
- (define tree1
- '(html
- (head (title "Slides"))
- (body
- (p (@ (align "center"))
- (table (@ (style "font-size: x-large"))
- (tr
- (td (@ (align "right")) "Talks ")
- (td (@ (align "center")) " = ")
- (td " slides + transition"))
- (tr (td)
- (td (@ (align "center")) " = ")
- (td " data + control"))
- (tr (td)
- (td (@ (align "center")) " = ")
- (td " programs"))))
- (ul
- (li (a (@ (href "slides/slide0001.gif")) "Introduction"))
- (li (a (@ (href "slides/slide0010.gif")) "Summary")))
- )))
- ;; Example from a posting "Re: DrScheme and XML",
- ;; Shriram Krishnamurthi, comp.lang.scheme, Nov. 26. 1999.
- ;; http://www.deja.com/getdoc.xp?AN=553507805
- (define tree3
- '(poem (@ (title "The Lovesong of J. Alfred Prufrock")
- (poet "T. S. Eliot"))
- (stanza
- (line "Let us go then, you and I,")
- (line "When the evening is spread out against the sky")
- (line "Like a patient etherized upon a table:"))
- (stanza
- (line "In the room the women come and go")
- (line "Talking of Michaelangelo."))))
- (define (run-test selector node expected)
- (pass-if expected
- (equal? expected (selector node))))
- (with-test-prefix "test-all"
- ;; Location path, full form: child::para
- ;; Location path, abbreviated form: para
- ;; selects the para element children of the context node
- (let ((tree
- '(elem (@) (para (@) "para") (br (@)) "cdata" (para (@) "second par"))
- )
- (expected '((para (@) "para") (para (@) "second par")))
- )
- (run-test (select-kids (node-typeof? 'para)) tree expected)
- (run-test (sxpath '(para)) tree expected))
- ;; Location path, full form: child::*
- ;; Location path, abbreviated form: *
- ;; selects all element children of the context node
- (let ((tree
- '(elem (@) (para (@) "para") (br (@)) "cdata" (para "second par"))
- )
- (expected
- '((para (@) "para") (br (@)) (para "second par")))
- )
- (run-test (select-kids (node-typeof? '*)) tree expected)
- (run-test (sxpath '(*)) tree expected))
- ;; Location path, full form: child::text()
- ;; Location path, abbreviated form: text()
- ;; selects all text node children of the context node
- (let ((tree
- '(elem (@) (para (@) "para") (br (@)) "cdata" (para "second par"))
- )
- (expected
- '("cdata"))
- )
- (run-test (select-kids (node-typeof? '*text*)) tree expected)
- (run-test (sxpath '(*text*)) tree expected))
- ;; Location path, full form: child::node()
- ;; Location path, abbreviated form: node()
- ;; selects all the children of the context node, whatever their node type
- (let* ((tree
- '(elem (@) (para (@) "para") (br (@)) "cdata" (para "second par"))
- )
- (expected (cdr tree))
- )
- (run-test (select-kids (node-typeof? '*any*)) tree expected)
- (run-test (sxpath '(*any*)) tree expected)
- )
- ;; Location path, full form: child::*/child::para
- ;; Location path, abbreviated form: */para
- ;; selects all para grandchildren of the context node
- (let ((tree
- '(elem (@) (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para "third para")))
- )
- (expected
- '((para "third para")))
- )
- (run-test
- (node-join (select-kids (node-typeof? '*))
- (select-kids (node-typeof? 'para)))
- tree expected)
- (run-test (sxpath '(* para)) tree expected)
- )
- ;; Location path, full form: attribute::name
- ;; Location path, abbreviated form: @name
- ;; selects the 'name' attribute of the context node
- (let ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para (@) "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- (expected
- '((name "elem")))
- )
- (run-test
- (node-join (select-kids (node-typeof? '@))
- (select-kids (node-typeof? 'name)))
- tree expected)
- (run-test (sxpath '(@ name)) tree expected)
- )
- ;; Location path, full form: attribute::*
- ;; Location path, abbreviated form: @*
- ;; selects all the attributes of the context node
- (let ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- (expected
- '((name "elem") (id "idz")))
- )
- (run-test
- (node-join (select-kids (node-typeof? '@))
- (select-kids (node-typeof? '*)))
- tree expected)
- (run-test (sxpath '(@ *)) tree expected)
- )
- ;; Location path, full form: descendant::para
- ;; Location path, abbreviated form: .//para
- ;; selects the para element descendants of the context node
- (let ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- (expected
- '((para (@) "para") (para "second par") (para (@) "third para")))
- )
- (run-test
- (node-closure (node-typeof? 'para))
- tree expected)
- (run-test (sxpath '(// para)) tree expected)
- )
- ;; Location path, full form: self::para
- ;; Location path, abbreviated form: _none_
- ;; selects the context node if it is a para element; otherwise selects nothing
- (let ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- )
- (run-test (node-self (node-typeof? 'para)) tree '())
- (run-test (node-self (node-typeof? 'elem)) tree (list tree))
- )
- ;; Location path, full form: descendant-or-self::node()
- ;; Location path, abbreviated form: //
- ;; selects the context node, all the children (including attribute nodes)
- ;; of the context node, and all the children of all the (element)
- ;; descendants of the context node.
- ;; This is _almost_ a powerset of the context node.
- (let* ((tree
- '(para (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- (expected
- (cons tree
- (append (cdr tree)
- '((@) "para" (@) "second par"
- (@ (name "aa")) (para (@) "third para")
- (@) "third para"))))
- )
- (run-test
- (node-or
- (node-self (node-typeof? '*any*))
- (node-closure (node-typeof? '*any*)))
- tree expected)
- (run-test (sxpath '(//)) tree expected)
- )
- ;; Location path, full form: ancestor::div
- ;; Location path, abbreviated form: _none_
- ;; selects all div ancestors of the context node
- ;; This Location expression is equivalent to the following:
- ; /descendant-or-self::div[descendant::node() = curr_node]
- ;; This shows that the ancestor:: axis is actually redundant. Still,
- ;; it can be emulated as the following SXPath expression demonstrates.
- ;; The insight behind "ancestor::div" -- selecting all "div" ancestors
- ;; of the current node -- is
- ;; S[ancestor::div] context_node =
- ;; { y | y=subnode*(root), context_node=subnode(subnode*(y)),
- ;; isElement(y), name(y) = "div" }
- ;; We observe that
- ;; { y | y=subnode*(root), pred(y) }
- ;; can be expressed in SXPath as
- ;; ((node-or (node-self pred) (node-closure pred)) root-node)
- ;; The composite predicate 'isElement(y) & name(y) = "div"' corresponds to
- ;; (node-self (node-typeof? 'div)) in SXPath. Finally, filter
- ;; context_node=subnode(subnode*(y)) is tantamount to
- ;; (node-closure (node-eq? context-node)), whereas node-reduce denotes the
- ;; the composition of converters-predicates in the filtering context.
- (let*
- ((root
- '(div (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para (@) "second par")
- (div (@ (name "aa")) (para (@) "third para"))))
- (context-node ; /descendant::any()[child::text() == "third para"]
- (car
- ((node-closure
- (select-kids
- (node-equal? "third para")))
- root)))
- (pred
- (node-reduce (node-self (node-typeof? 'div))
- (node-closure (node-eq? context-node))
- ))
- )
- (run-test
- (node-or
- (node-self pred)
- (node-closure pred))
- root
- (cons root
- '((div (@ (name "aa")) (para (@) "third para")))))
- )
- ;; Location path, full form: child::div/descendant::para
- ;; Location path, abbreviated form: div//para
- ;; selects the para element descendants of the div element
- ;; children of the context node
- (let ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")
- (div (para "fourth para"))))
- )
- (expected
- '((para (@) "third para") (para "fourth para")))
- )
- (run-test
- (node-join
- (select-kids (node-typeof? 'div))
- (node-closure (node-typeof? 'para)))
- tree expected)
- (run-test (sxpath '(div // para)) tree expected)
- )
- ;; Location path, full form: /descendant::olist/child::item
- ;; Location path, abbreviated form: //olist/item
- ;; selects all the item elements that have an olist parent (which is not root)
- ;; and that are in the same document as the context node
- ;; See the following test.
- ;; Location path, full form: /descendant::td/attribute::align
- ;; Location path, abbreviated form: //td/@align
- ;; Selects 'align' attributes of all 'td' elements in tree1
- (let ((tree tree1)
- (expected
- '((align "right") (align "center") (align "center") (align "center"))
- ))
- (run-test
- (node-join
- (node-closure (node-typeof? 'td))
- (select-kids (node-typeof? '@))
- (select-kids (node-typeof? 'align)))
- tree expected)
- (run-test (sxpath '(// td @ align)) tree expected)
- )
- ;; Location path, full form: /descendant::td[attribute::align]
- ;; Location path, abbreviated form: //td[@align]
- ;; Selects all td elements that have an attribute 'align' in tree1
- (let ((tree tree1)
- (expected
- '((td (@ (align "right")) "Talks ") (td (@ (align "center")) " = ")
- (td (@ (align "center")) " = ") (td (@ (align "center")) " = "))
- ))
- (run-test
- (node-reduce
- (node-closure (node-typeof? 'td))
- (filter
- (node-join
- (select-kids (node-typeof? '@))
- (select-kids (node-typeof? 'align)))))
- tree expected)
- (run-test (sxpath `(// td ,(node-self (sxpath '(@ align))))) tree expected)
- (run-test (sxpath '(// (td (@ align)))) tree expected)
- (run-test (sxpath '(// ((td) (@ align)))) tree expected)
- ;; note! (sxpath ...) is a converter. Therefore, it can be used
- ;; as any other converter, for example, in the full-form SXPath.
- ;; Thus we can mix the full and abbreviated form SXPath's freely.
- (run-test
- (node-reduce
- (node-closure (node-typeof? 'td))
- (filter
- (sxpath '(@ align))))
- tree expected)
- )
- ;; Location path, full form: /descendant::td[attribute::align = "right"]
- ;; Location path, abbreviated form: //td[@align = "right"]
- ;; Selects all td elements that have an attribute align = "right" in tree1
- (let ((tree tree1)
- (expected
- '((td (@ (align "right")) "Talks "))
- ))
- (run-test
- (node-reduce
- (node-closure (node-typeof? 'td))
- (filter
- (node-join
- (select-kids (node-typeof? '@))
- (select-kids (node-equal? '(align "right"))))))
- tree expected)
- (run-test (sxpath '(// (td (@ (equal? (align "right")))))) tree expected)
- )
- ;; Location path, full form: child::para[position()=1]
- ;; Location path, abbreviated form: para[1]
- ;; selects the first para child of the context node
- (let ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- (expected
- '((para (@) "para"))
- ))
- (run-test
- (node-reduce
- (select-kids (node-typeof? 'para))
- (node-pos 1))
- tree expected)
- (run-test (sxpath '((para 1))) tree expected)
- )
- ;; Location path, full form: child::para[position()=last()]
- ;; Location path, abbreviated form: para[last()]
- ;; selects the last para child of the context node
- (let ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- (expected
- '((para "second par"))
- ))
- (run-test
- (node-reduce
- (select-kids (node-typeof? 'para))
- (node-pos -1))
- tree expected)
- (run-test (sxpath '((para -1))) tree expected)
- )
- ;; Illustrating the following Note of Sec 2.5 of XPath:
- ;; "NOTE: The location path //para[1] does not mean the same as the
- ;; location path /descendant::para[1]. The latter selects the first
- ;; descendant para element; the former selects all descendant para
- ;; elements that are the first para children of their parents."
- (let ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- )
- (run-test
- (node-reduce ; /descendant::para[1] in SXPath
- (node-closure (node-typeof? 'para))
- (node-pos 1))
- tree '((para (@) "para")))
- (run-test (sxpath '(// (para 1))) tree
- '((para (@) "para") (para (@) "third para")))
- )
- ;; Location path, full form: parent::node()
- ;; Location path, abbreviated form: ..
- ;; selects the parent of the context node. The context node may be
- ;; an attribute node!
- ;; For the last test:
- ;; Location path, full form: parent::*/attribute::name
- ;; Location path, abbreviated form: ../@name
- ;; Selects the name attribute of the parent of the context node
- (let* ((tree
- '(elem (@ (name "elem") (id "idz"))
- (para (@) "para") (br (@)) "cdata" (para "second par")
- (div (@ (name "aa")) (para (@) "third para")))
- )
- (para1 ; the first para node
- (car ((sxpath '(para)) tree)))
- (para3 ; the third para node
- (car ((sxpath '(div para)) tree)))
- (div ; div node
- (car ((sxpath '(// div)) tree)))
- )
- (run-test
- (node-parent tree)
- para1 (list tree))
- (run-test
- (node-parent tree)
- para3 (list div))
- (run-test ; checking the parent of an attribute node
- (node-parent tree)
- ((sxpath '(@ name)) div) (list div))
- (run-test
- (node-join
- (node-parent tree)
- (select-kids (node-typeof? '@))
- (select-kids (node-typeof? 'name)))
- para3 '((name "aa")))
- (run-test
- (sxpath `(,(node-parent tree) @ name))
- para3 '((name "aa")))
- )
- ;; Location path, full form: following-sibling::chapter[position()=1]
- ;; Location path, abbreviated form: none
- ;; selects the next chapter sibling of the context node
- ;; The path is equivalent to
- ;; let cnode = context-node
- ;; in
- ;; parent::* / child::chapter [take-after node_eq(self::*,cnode)]
- ;; [position()=1]
- (let* ((tree
- '(document
- (preface "preface")
- (chapter (@ (id "one")) "Chap 1 text")
- (chapter (@ (id "two")) "Chap 2 text")
- (chapter (@ (id "three")) "Chap 3 text")
- (chapter (@ (id "four")) "Chap 4 text")
- (epilogue "Epilogue text")
- (appendix (@ (id "A")) "App A text")
- (References "References"))
- )
- (a-node ; to be used as a context node
- (car ((sxpath '(// (chapter (@ (equal? (id "two")))))) tree)))
- (expected
- '((chapter (@ (id "three")) "Chap 3 text")))
- )
- (run-test
- (node-reduce
- (node-join
- (node-parent tree)
- (select-kids (node-typeof? 'chapter)))
- (take-after (node-eq? a-node))
- (node-pos 1)
- )
- a-node expected)
- )
- ;; preceding-sibling::chapter[position()=1]
- ;; selects the previous chapter sibling of the context node
- ;; The path is equivalent to
- ;; let cnode = context-node
- ;; in
- ;; parent::* / child::chapter [take-until node_eq(self::*,cnode)]
- ;; [position()=-1]
- (let* ((tree
- '(document
- (preface "preface")
- (chapter (@ (id "one")) "Chap 1 text")
- (chapter (@ (id "two")) "Chap 2 text")
- (chapter (@ (id "three")) "Chap 3 text")
- (chapter (@ (id "four")) "Chap 4 text")
- (epilogue "Epilogue text")
- (appendix (@ (id "A")) "App A text")
- (References "References"))
- )
- (a-node ; to be used as a context node
- (car ((sxpath '(// (chapter (@ (equal? (id "three")))))) tree)))
- (expected
- '((chapter (@ (id "two")) "Chap 2 text")))
- )
- (run-test
- (node-reduce
- (node-join
- (node-parent tree)
- (select-kids (node-typeof? 'chapter)))
- (take-until (node-eq? a-node))
- (node-pos -1)
- )
- a-node expected)
- )
- ;; /descendant::figure[position()=42]
- ;; selects the forty-second figure element in the document
- ;; See the next example, which is more general.
- ;; Location path, full form:
- ;; child::table/child::tr[position()=2]/child::td[position()=3]
- ;; Location path, abbreviated form: table/tr[2]/td[3]
- ;; selects the third td of the second tr of the table
- (let ((tree ((node-closure (node-typeof? 'p)) tree1))
- (expected
- '((td " data + control"))
- ))
- (run-test
- (node-join
- (select-kids (node-typeof? 'table))
- (node-reduce (select-kids (node-typeof? 'tr))
- (node-pos 2))
- (node-reduce (select-kids (node-typeof? 'td))
- (node-pos 3)))
- tree expected)
- (run-test (sxpath '(table (tr 2) (td 3))) tree expected)
- )
- ;; Location path, full form:
- ;; child::para[attribute::type='warning'][position()=5]
- ;; Location path, abbreviated form: para[@type='warning'][5]
- ;; selects the fifth para child of the context node that has a type
- ;; attribute with value warning
- (let ((tree
- '(chapter
- (para "para1")
- (para (@ (type "warning")) "para 2")
- (para (@ (type "warning")) "para 3")
- (para (@ (type "warning")) "para 4")
- (para (@ (type "warning")) "para 5")
- (para (@ (type "warning")) "para 6"))
- )
- (expected
- '((para (@ (type "warning")) "para 6"))
- ))
- (run-test
- (node-reduce
- (select-kids (node-typeof? 'para))
- (filter
- (node-join
- (select-kids (node-typeof? '@))
- (select-kids (node-equal? '(type "warning")))))
- (node-pos 5))
- tree expected)
- (run-test (sxpath '( (((para (@ (equal? (type "warning"))))) 5 ) ))
- tree expected)
- (run-test (sxpath '( (para (@ (equal? (type "warning"))) 5 ) ))
- tree expected)
- )
- ;; Location path, full form:
- ;; child::para[position()=5][attribute::type='warning']
- ;; Location path, abbreviated form: para[5][@type='warning']
- ;; selects the fifth para child of the context node if that child has a 'type'
- ;; attribute with value warning
- (let ((tree
- '(chapter
- (para "para1")
- (para (@ (type "warning")) "para 2")
- (para (@ (type "warning")) "para 3")
- (para (@ (type "warning")) "para 4")
- (para (@ (type "warning")) "para 5")
- (para (@ (type "warning")) "para 6"))
- )
- (expected
- '((para (@ (type "warning")) "para 5"))
- ))
- (run-test
- (node-reduce
- (select-kids (node-typeof? 'para))
- (node-pos 5)
- (filter
- (node-join
- (select-kids (node-typeof? '@))
- (select-kids (node-equal? '(type "warning"))))))
- tree expected)
- (run-test (sxpath '( (( (para 5)) (@ (equal? (type "warning"))))))
- tree expected)
- (run-test (sxpath '( (para 5 (@ (equal? (type "warning")))) ))
- tree expected)
- )
- ;; Location path, full form:
- ;; child::*[self::chapter or self::appendix]
- ;; Location path, semi-abbreviated form: *[self::chapter or self::appendix]
- ;; selects the chapter and appendix children of the context node
- (let ((tree
- '(document
- (preface "preface")
- (chapter (@ (id "one")) "Chap 1 text")
- (chapter (@ (id "two")) "Chap 2 text")
- (chapter (@ (id "three")) "Chap 3 text")
- (epilogue "Epilogue text")
- (appendix (@ (id "A")) "App A text")
- (References "References"))
- )
- (expected
- '((chapter (@ (id "one")) "Chap 1 text")
- (chapter (@ (id "two")) "Chap 2 text")
- (chapter (@ (id "three")) "Chap 3 text")
- (appendix (@ (id "A")) "App A text"))
- ))
- (run-test
- (node-join
- (select-kids (node-typeof? '*))
- (filter
- (node-or
- (node-self (node-typeof? 'chapter))
- (node-self (node-typeof? 'appendix)))))
- tree expected)
- (run-test (sxpath `(* ,(node-or (node-self (node-typeof? 'chapter))
- (node-self (node-typeof? 'appendix)))))
- tree expected)
- )
- ;; Location path, full form: child::chapter[child::title='Introduction']
- ;; Location path, abbreviated form: chapter[title = 'Introduction']
- ;; selects the chapter children of the context node that have one or more
- ;; title children with string-value equal to Introduction
- ;; See a similar example: //td[@align = "right"] above.
- ;; Location path, full form: child::chapter[child::title]
- ;; Location path, abbreviated form: chapter[title]
- ;; selects the chapter children of the context node that have one or
- ;; more title children
- ;; See a similar example //td[@align] above.
- (let ((tree tree3)
- (expected
- '("Let us go then, you and I," "In the room the women come and go")
- ))
- (run-test
- (node-join
- (node-closure (node-typeof? 'stanza))
- (node-reduce
- (select-kids (node-typeof? 'line)) (node-pos 1))
- (select-kids (node-typeof? '*text*)))
- tree expected)
- (run-test (sxpath '(// stanza (line 1) *text*)) tree expected)
- )
- )
|