SXML serializer into XML and HTML Partial conformance with [1] XSLT 2.0 and XQuery 1.0 Serialization W3C Candidate Recommendation 3 November 2005 http://www.w3.org/TR/2005/CR-xslt-xquery-serialization-20051103/ This software is in Public Domain. IT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. Please send bug reports and comments to<EMAIL_ADDRESS>Dmitry Lizorkin
(srl:map-append func lst) = (apply append (map func lst)) A simplified analogue of `map-union' from "sxpathlib.scm"
Analogue of `assoc' However, search is performed by `cdr' of each alist member and `string=?' is used for comparison
Analogue of `member' for strings that uses case insensitive comparison
Analogue of `member' The end of the `lst' is returned, from the first member that satisfies the `pred?'
A string consisting of a single newline character
A simplified implementation of `select-kids' is sufficienf for the serializer
Separates the list into two lists with respect to the predicate Returns: (values res-lst1 res-lst2) res-lst1 - contains all members from the input lst that satisfy the pred? res-lst2 - contains the remaining members of the input lst
A simplified implementation of `sxml:clean-fragments'
A very much simplified analogue of `sxml:display-fragments' for fragments that have no more than two levels of nesting fragments-level2 ::= (listof fragments-level1) fragments-level1 ::= string | (listof string)
Splits an SXML `name' into namespace id/uri and local part Returns: (cons namespace-id local-part) local-part - string namespace-id - string or #f if the `name' does not have a prefix
Converts SXML atomic object to a string. Keeps non-atomic object unchanged. A simplified analogue of applying the XPath `string(.)' function to atomic object.
Whether an SXML element is empty
<namespace-assoc> is defined in the SXML specification as <namespace-assoc> ::= ( <namespace-id> "URI" original-prefix? )
Conventional namespace prefix referred to in XML-related specifications These prefixes are used for serializing the corresponding namespace URIs by default, unless a different prefix is supplied
Returns (listof <namespace-assoc>) for the given SXML element
Returns (listof <namespace-assoc>) for the SXML document node
Extract original prefix-binding from `namespace-assoc-lst' namespace-assoc-lst ::= (listof <namespace-assoc>) <namespace-assoc> ::= ( <namespace-id> "URI" original-prefix? ) Returns: (listof (cons original-prefix "URI"))
Returns the new value of `space-preserve?' in accordance with the value of xml:space attribute probably presented for the given SXML element `elem' space-preserve? ::= #t | #f - whether the SXML subtree inherits the xml:space attribute with the value "preserve"
Sect. 2 in [1]
Performs sequence normalization in accordance with [1] Returns the SXML document node
Escaping in accordance with [1] and [2]: [2] Extensible Markup Language (XML) 1.0 (Third Edition) W3C Recommendation 04 February 2004 http://www.w3.org/TR/2004/REC-xml-20040204
Returns #f if a given character `ch' is in XML character range [2] Otherwise, returns a string representing the character reference for that character
Represents a given string `str' as a CDATA section
Associative lists of characters to be escaped in XML character data and attribute values respectively [2]
Escape a string with the `srl:xml-char-escaped' and with the `escape-alist' supplied escape-alist ::= (listof (cons char string)) html-method? ::= #t | #f Returns the escaped string
[3] Neil W. Van Dyke. HtmlPrag: Pragmatic Parsing and Emitting of HTML using SXML and SHTML Version 0.16, 2005-12-18, http://www.neilvandyke.org/htmlprag/
"..SHTML adds a special & syntax for non-ASCII (or non-Extended-ASCII) characters. The syntax is (& val), where val is a symbol or string naming with the symbolic name of the character, or an integer with the numeric value of the character." [3] entity ::= `(& ,val) val ::= symbol | string | number Returns the string representation for the entity
declared-ns-prefixes ::= (listof (cons prefix-string namespace-uri)) prefix-string, namespace-uri - strings
Returns the string representation for a QName prefix-string ::= string or #f if the name contains no prefix TODO: should check names for proper characters
Returns the list of strings that constitute the serialized representation for the attribute. Inserts a whitespace symbol in the beginning method ::= 'xml | 'html
Returns the list of strings that constitute the serialized representation for the namespace declaration. Inserts a whitespace symbol in the beginning ATTENTION: character escaping for namespace URI may be improper, study this issue
According to SXML specification, <comment> ::= ( *COMMENT* "comment string" ) ATTENTION: in the case of ill-formed comment, should probably report an error instead of recovering
According to SXML specification, <PI> ::= ( *PI* pi-target <annotations>? "processing instruction content string" ) method ::= 'xml | 'html Subsect 7.3 in [1]: "The HTML output method MUST terminate processing instructions with > rather than ?>." ATTENTION: in the case of ill-formed PI content string, should probably report an error instead of recovering
Returns: (values prefix-string namespace-uri local-part declaration-required?) prefix-string - namespace prefix to be given to the serialized name: a string or #f if no prefix is required namespace-uri - the namespace URI for the given `name', #f if the name has no namespace URI local-part - local part of the name declaration-required ::= #t | #f - whether `prefix' has to be declared
Constructs start and end tags for an SXML element `elem' method ::= 'xml | 'html Returns: (values start-tag end-tag ns-prefix-assig namespace-assoc declared-ns-prefixes) start-tag ::= (listof string) end-tag ::= (listof string) or #f for empty element TODO: escape URI attributes for HTML TODO: indentation probably should be made between attribute declarations
indentation ::= (listof string) or #f - a list of whitespace strings depending on the node nesting or #f if no indent is required space-preserve? ::= #t | #f - whether the subtree inherits the xml:space attribute with the value "preserve" cdata-section-elements ::= (listof symbol) - list of element names whose child nodes are to be output with CDATA section text-node-handler :: string -> string - a function that performs a proper character escaping for the given node if it is a text node TODO: do not insert whitespaces adjacent to HTML %inline elements in HTML output method
Creates the serialized representation for the XML declaration Returns: (listof string) version ::= string | number standalone ::= 'yes | 'no | 'omit
omit-xml-declaration? ::= #t | #f standalone ::= 'yes | 'no | 'omit version ::= string | number
and with no overhead of parameters parsing. ATTENTION: As future versions of this library may provide support for additional serialization parameters, the functions `srl:sxml->string' and `srl:display-sxml' specified in this subsections may have a different number of their arguments in the future versions of the library.
Returns a string that contains the serialized representation for `sxml-obj'. cdata-section-elements ::= (listof sxml-name) indent ::= #t | #f | whitespace-string method = 'xml | 'html ns-prefix-assign ::= (listof (cons prefix-symbol namespace-uri-string)) omit-xml-declaration? ::= #t | #f standalone ::= 'yes | 'no | 'omit version ::= number | string
Writes the serialized representation of the `sxml-obj' to an output port `port'. The result returned by the function is unspecified.
serialization params supported by this implementation
procedure srl:parameterizable :: SXML-OBJ [PORT] {PARAM}* -> -> STRING|unspecified sxml-obj - an SXML object to serialize param ::= (cons param-name param-value) param-name ::= symbol 1. cdata-section-elements value ::= (listof sxml-elem-name) sxml-elem-name ::= symbol 2. indent value ::= 'yes | #t | 'no | #f | whitespace-string 3. method value ::= 'xml | 'html 4. ns-prefix-assig value ::= (listof (cons prefix namespace-uri)) prefix ::= symbol namespace-uri ::= string 5. omit-xml-declaration? value ::= 'yes | #t | 'no | #f 6. standalone value ::= 'yes | #t | 'no | #f | 'omit 7. version value ::= string | number ATTENTION: If a parameter name is unexpected or a parameter value is ill-formed, the parameter is silently ignored. Probably, a warning message in such a case would be more appropriate. Example: (srl:parameterizable '(tag (@ (attr "value")) (nested "text node") (empty)) (current-output-port) '(method . xml) ; XML output method is used by default '(indent . "\t") ; use a single tabulation to indent nested elements '(omit-xml-declaration . #f) ; add XML declaration '(standalone . yes) ; denote a standalone XML document '(version . "1.0")) ; XML version
These functions use only a subset of serializer functionality, however, this subset seems sufficient for most practical purposes.
procedure srl:sxml->xml :: SXML-OBJ [PORT-OR-FILENAME] -> STRING|unspecified Serializes the `sxml-obj' into XML, with indentation to facilitate readability by a human. sxml-obj - an SXML object (a node or a nodeset) to be serialized port-or-filename - an output port or an output file name, an optional argument If `port-or-filename' is not supplied, the functions return a string that contains the serialized representation of the `sxml-obj'. If `port-or-filename' is supplied and is a port, the functions write the serialized representation of `sxml-obj' to this port and return an unspecified result. If `port-or-filename' is supplied and is a string, this string is treated as an output filename, the serialized representation of `sxml-obj' is written to that filename and an unspecified result is returned. If a file with the given name already exists, the effect is unspecified.
procedure srl:sxml->xml-noindent :: SXML-OBJ [PORT-OR-FILENAME] -> -> STRING|unspecified Serializes the `sxml-obj' into XML, without indentation.
procedure srl:sxml->html :: SXML-OBJ [PORT-OR-FILENAME] -> STRING|unspecified Serializes the `sxml-obj' into HTML, with indentation to facilitate readability by a human. sxml-obj - an SXML object (a node or a nodeset) to be serialized port-or-filename - an output port or an output file name, an optional argument If `port-or-filename' is not supplied, the functions return a string that contains the serialized representation of the `sxml-obj'. If `port-or-filename' is supplied and is a port, the functions write the serialized representation of `sxml-obj' to this port and return an unspecified result. If `port-or-filename' is supplied and is a string, this string is treated as an output filename, the serialized representation of `sxml-obj' is written to that filename and an unspecified result is returned. If a file with the given name already exists, the effect is unspecified.
procedure srl:sxml->html-noindent :: SXML-OBJ [PORT-OR-FILENAME] -> -> STRING|unspecified Serializes the `sxml-obj' into HTML, without indentation.
(srl:map-append func lst) = (apply append (map func lst)) A simplified analogue of `map-union' from "sxpathlib.scm"
(define (srl:map-append func lst) (if (null? lst) lst (append (func (car lst)) (srl:map-append func (cdr lst)))))
procedure srl:apply-string-append :: STR-LST -> STRING str-lst ::= (listof string) Concatenates `str-lst' members into a single string (srl:apply-string-append str-lst) = (apply string-append str-lst)
(cond-expand (chicken ; In Chicken, procedures are generally limited to 126 arguments ; http://www.call-with-current-continuation.org/ ; Due to this Chicken limitation, we cannot apply `string-append' directly ; for a potentially long `str-lst' ; Similar to R5RS 'list-tail' but returns the new list consisting of the ; first 'k' members of 'lst' (define (srl:list-head lst k) (if (or (null? lst) (zero? k)) '() (cons (car lst) (srl:list-head (cdr lst) (- k 1))))) ; Because of Chicken 126-argument limitation, I do not care of intermediate ; garbage produced in the following solution: (define (srl:apply-string-append str-lst) (cond ((null? str-lst) "") ((null? (cdr str-lst)) (car str-lst)) (else ; at least two members (let ((middle (inexact->exact (round (/ (length str-lst) 2))))) (string-append (srl:apply-string-append (srl:list-head str-lst middle)) (srl:apply-string-append (list-tail str-lst middle))))))) ) (else (define (srl:apply-string-append str-lst) (apply string-append str-lst)) ))
Analogue of `assoc' However, search is performed by `cdr' of each alist member and `string=?' is used for comparison
(define (srl:assoc-cdr-string= item alist) (cond ((null? alist) #f) ((string=? (cdar alist) item) (car alist)) (else (srl:assoc-cdr-string= item (cdr alist)))))
Analogue of `member' for strings that uses case insensitive comparison
(define (srl:member-ci str lst) (cond ((null? lst) #f) ((string-ci=? str (car lst)) lst) (else (srl:member-ci str (cdr lst)))))
Analogue of `member' The end of the `lst' is returned, from the first member that satisfies the `pred?'
(define (srl:mem-pred pred? lst) (cond ((null? lst) #f) ((pred? (car lst)) lst) (else (srl:mem-pred pred? (cdr lst)))))
The newline character
(cond-expand ((or scheme48 scsh) (define srl:char-nl (ascii->char 10))) (else (define srl:char-nl (integer->char 10))))
A string consisting of a single newline character
(define srl:newline (string srl:char-nl))
A simplified implementation of `select-kids' is sufficienf for the serializer
(define (srl:select-kids test-pred?) (lambda (node) ; node or node-set (cond ((null? node) node) ((not (pair? node)) '()) ; No children ((symbol? (car node)) (filter test-pred? (cdr node))) (else (srl:map-append (srl:select-kids test-pred?) node)))))
Separates the list into two lists with respect to the predicate Returns: (values res-lst1 res-lst2) res-lst1 - contains all members from the input lst that satisfy the pred? res-lst2 - contains the remaining members of the input lst
(define (srl:separate-list pred? lst) (let loop ((lst lst) (satisfy '()) (rest '())) (cond ((null? lst) (values (reverse satisfy) (reverse rest))) ((pred? (car lst)) ; the first member satisfies the predicate (loop (cdr lst) (cons (car lst) satisfy) rest)) (else (loop (cdr lst) satisfy (cons (car lst) rest))))))
A simplified implementation of `sxml:clean-fragments'
(define (srl:clean-fragments fragments) (reverse (let loop ((fragments fragments) (result '())) (cond ((null? fragments) result) ((null? (car fragments)) (loop (cdr fragments) result)) ((pair? (car fragments)) (loop (cdr fragments) (loop (car fragments) result))) (else (loop (cdr fragments) (cons (car fragments) result)))))))
A very much simplified analogue of `sxml:display-fragments' for fragments that have no more than two levels of nesting fragments-level2 ::= (listof fragments-level1) fragments-level1 ::= string | (listof string)
(define (srl:display-fragments-2nesting fragments-level2 port) (for-each (lambda (level1) (if (pair? level1) (for-each (lambda (x) (display x port)) level1) (display level1 port))) fragments-level2))
Splits an SXML `name' into namespace id/uri and local part Returns: (cons namespace-id local-part) local-part - string namespace-id - string or #f if the `name' does not have a prefix
(define (srl:split-name name) (let* ((name-str (symbol->string name)) (lng (string-length name-str))) (let iter ((i (- lng 1))) (cond ((< i 0) ; name scanned, #\: not found (cons #f name-str)) ((char=? (string-ref name-str i) #\:) (cons (substring name-str 0 i) (substring name-str (+ i 1) lng))) (else (iter (- i 1)))))))
Converts SXML atomic object to a string. Keeps non-atomic object unchanged. A simplified analogue of applying the XPath `string(.)' function to atomic object.
(define (srl:atomic->string obj) (cond ((or (pair? obj) ; non-atomic type (string? obj)) obj) ((number? obj) (number->string obj)) ((boolean? obj) (if obj "true" "false")) (else ; unexpected type ; ATTENTION: should probably raise an error here obj)))
Whether an SXML element is empty
(define (srl:empty-elem? elem) (or (null? (cdr elem)) ; just the name (and (null? (cddr elem)) ; just the name and attributes (pair? (cadr elem)) (eq? (caadr elem) '@)) (and (not (null? (cddr elem))) ; name, attributes, and SXML 2.X aux-list (null? (cdddr elem)) (pair? (caddr elem)) (eq? (caaddr elem) '@@))))
Performs sequence normalization in accordance with [1] Returns the SXML document node
(define (srl:normalize-sequence node-or-sequence) (letrec ((normaliz-step-1 ; "If the sequence that is input to serialization is empty, create a ; sequence S1 that consists of a zero-length string. Otherwise, copy ; each item in the sequence that is input to serialization to create ; the new sequence S1." [1] (lambda (node-or-seq) (cond ((null? node-or-seq) ; empty sequence '("")) ; Effect of `as-nodeset' from "sxpathlib.scm" ((or (not (pair? node-or-seq)) ; single item (symbol? (car node-or-seq))) ; single node (list node-or-seq)) (else node-or-seq)))) (normaliz-step-2 ; "For each item in S1, if the item is atomic, obtain the lexical ; representation of the item by casting it to an xs:string and copy ; the string representation to the new sequence; otherwise, copy the ; item, which will be a node, to the new sequence. The new sequence is ; S2." [1] (lambda (seq) (map (lambda (item) (srl:atomic->string item)) seq))) (normaliz-step-3 ; "For each subsequence of adjacent strings in S2, copy a single ; string to the new sequence equal to the values of the strings in the ; subsequence concatenated in order, each separated by a single space. ; Copy all other items to the new sequence. The new sequence is S3." (lambda (seq) (let loop ((src (reverse seq)) (res '())) (cond ((null? src) res) ((string? (car src)) (let adjacent ((src (cdr src)) (adj-strs (list (car src)))) (cond ((null? src) ; source sequence is over (cons (srl:apply-string-append adj-strs) res)) ((string? (car src)) (adjacent (cdr src) (cons (car src) (cons " " adj-strs)))) (else (loop (cdr src) (cons (car src) (cons (srl:apply-string-append adj-strs) res))))))) (else (loop (cdr src) (cons (car src) res))))))) ; Step 4 from [1] is redundant for SXML, since SXML text nodes are not ; distinquished from strings (normaliz-step-5 ; "For each item in S4, if the item is a document node, copy its ; children to the new sequence; otherwise, copy the item to the new ; sequence. The new sequence is S5." [1] (lambda (seq) (cond ((null? seq) seq) ((and (pair? (car seq)) (eq? (caar seq) '*TOP*)) ; Document node (append (cdar seq) (normaliz-step-5 (cdr seq)))) (else (cons (car seq) (normaliz-step-5 (cdr seq))))))) (normaliz-step-6 ; "For each subsequence of adjacent text nodes in S5, copy a single ; text node to the new sequence equal to the values of the text nodes ; in the subsequence concatenated in order. Any text nodes with values ; of zero length are dropped. Copy all other items to the new sequence. ; The new sequence is S6." [1] ; Much like Step 3; however, a space between adjacent strings is not ; inserted and the zero-length strings are removed (lambda (seq) (let loop ((src (reverse seq)) (res '())) (cond ((null? src) res) ((string? (car src)) (if (string=? (car src) "") ; empty string (loop (cdr src) res) (let adjacent ((src (cdr src)) (adj-strs (list (car src)))) (cond ((null? src) ; source sequence is over (cons (srl:apply-string-append adj-strs) res)) ((string? (car src)) ; If it is an empty string, the effect of its presense ; will be removed by string concatenation (adjacent (cdr src) (cons (car src) adj-strs))) (else (loop (cdr src) (cons (car src) (cons (srl:apply-string-append adj-strs) res)))))))) (else (loop (cdr src) (cons (car src) res))))))) (normaliz-step-7 ; "It is a serialization error [err:SENR0001] if an item in S6 is an ; attribute node or a namespace node. Otherwise, construct a new ; sequence, S7, that consists of a single document node and copy all ; the items in the sequence, which are all nodes, as children of that ; document node." [1] ; On this step, we should take care of SXML aux-lists ; ATTENTION: should generally raise an error in the presense of ; attribute nodes in a sequence. By nature of SXML 3.0, however, ; attribute nodes on the top level are treated as aux-nodes (lambda (seq) (call-with-values (lambda () (srl:separate-list (lambda (item) (and (pair? item) (or (eq? (car item) '@@) ; aux-list in SXML 2.X (eq? (car item) '@) ; aux-list in SXML 3.0 ))) seq)) (lambda (aux-lists body) (if (null? aux-lists) `(*TOP* ,@body) `(*TOP* (@ ,@(srl:map-append cdr aux-lists)) ,@body))))))) ; TODO: According to [1], if the normalized sequence does not have exactly ; one element node node child or has text node children, then the ; serialized output should be an XML external general parsed entity. ; However, external parsed entities are not currently handled by SSAX ; parser. Should think of a compromise between conformance and practical ; usability. (normaliz-step-7 (normaliz-step-6 (normaliz-step-5 (normaliz-step-3 (normaliz-step-2 (normaliz-step-1 node-or-sequence))))))))
Returns the string representation for a QName prefix-string ::= string or #f if the name contains no prefix TODO: should check names for proper characters
(define (srl:qname->string prefix-string local-part) (if prefix-string (string-append prefix-string ":" local-part) local-part))
indentation ::= (listof string) or #f - a list of whitespace strings depending on the node nesting or #f if no indent is required space-preserve? ::= #t | #f - whether the subtree inherits the xml:space attribute with the value "preserve" cdata-section-elements ::= (listof symbol) - list of element names whose child nodes are to be output with CDATA section text-node-handler :: string -> string - a function that performs a proper character escaping for the given node if it is a text node TODO: do not insert whitespaces adjacent to HTML %inline elements in HTML output method
(define (srl:node->nested-str-lst-recursive node method ns-prefix-assig namespace-assoc declared-ns-prefixes indentation space-preserve? cdata-section-elements text-node-handler) (if (not (pair? node)) ; text node (text-node-handler (srl:atomic->string node)) (case (car node) ; node name ((*COMMENT*) (srl:comment->str-lst node)) ((*PI*) (srl:processing-instruction->str-lst node method)) ((&) (srl:shtml-entity->char-data node)) ((*DECL*) ; recovering for non-SXML nodes '()) (else ; otherwise - an element node (call-with-values (lambda () (srl:construct-start-end-tags node method ns-prefix-assig namespace-assoc declared-ns-prefixes)) (lambda (start-tag end-tag ns-prefix-assig namespace-assoc declared-ns-prefixes) (if (not end-tag) ; empty element => recursion stops start-tag (let ((space-preserve? (srl:update-space-specifier node space-preserve?)) (text-node-handler (cond ((memq (car node) cdata-section-elements) srl:string->cdata-section) ((and (eq? method 'html) (srl:member-ci (symbol->string (car node)) '("script" "style"))) ; No escaping for strings inside these HTML elements (lambda (str) str)) (else srl:string->char-data))) (content ((srl:select-kids (lambda (node) ; TODO: support SXML entities (not (and (pair? node) (memq (car node) '(@ @@ *ENTITY*)))))) node))) (call-with-values (lambda () (cond ((or (not indentation) (and (eq? method 'html) (srl:member-ci (symbol->string (car node)) '("pre" "script" "style" "textarea")))) ; No indent - on this level and subsequent levels (values #f #f)) ((or space-preserve? (srl:mem-pred ; at least a single text node (lambda (node) (not (pair? node))) content)) ; No indent on this level, possible indent on nested levels (values #f indentation)) (else (values (cons srl:newline indentation) (cons (car indentation) indentation))))) (lambda (indent-here indent4recursive) (if indent-here (append start-tag (map (lambda (kid) (list indent-here (srl:node->nested-str-lst-recursive kid method ns-prefix-assig namespace-assoc declared-ns-prefixes indent4recursive space-preserve? cdata-section-elements text-node-handler))) content) (cons srl:newline (cons (cdr indentation) end-tag))) (append start-tag (map (lambda (kid) (srl:node->nested-str-lst-recursive kid method ns-prefix-assig namespace-assoc declared-ns-prefixes indent4recursive space-preserve? cdata-section-elements text-node-handler)) content) end-tag))))))))))))
(define (srl:display-node-out-recursive node port method ns-prefix-assig namespace-assoc declared-ns-prefixes indentation space-preserve? cdata-section-elements text-node-handler) (if (not (pair? node)) ; text node (display (text-node-handler (srl:atomic->string node)) port) (case (car node) ; node name ((*COMMENT*) (for-each (lambda (x) (display x port)) (srl:comment->str-lst node))) ((*PI*) (for-each (lambda (x) (display x port)) (srl:processing-instruction->str-lst node method))) ((&) (display (srl:shtml-entity->char-data node) port)) ((*DECL*) ; recovering for non-SXML nodes #f) (else ; otherwise - an element node (call-with-values (lambda () (srl:construct-start-end-tags node method ns-prefix-assig namespace-assoc declared-ns-prefixes)) (lambda (start-tag end-tag ns-prefix-assig namespace-assoc declared-ns-prefixes) (begin (srl:display-fragments-2nesting start-tag port) (if end-tag ; there exists content (let ((space-preserve? (srl:update-space-specifier node space-preserve?)) (text-node-handler (cond ((memq (car node) cdata-section-elements) srl:string->cdata-section) ((and (eq? method 'html) (srl:member-ci (symbol->string (car node)) '("script" "style"))) ; No escaping for strings inside these HTML elements (lambda (str) str)) (else srl:string->char-data))) (content ((srl:select-kids (lambda (node) ; TODO: support SXML entities (not (and (pair? node) (memq (car node) '(@ @@ *ENTITY*)))))) node))) (call-with-values (lambda () (cond ((or (not indentation) (and (eq? method 'html) (srl:member-ci (symbol->string (car node)) '("pre" "script" "style" "textarea")))) ; No indent - on this level and subsequent levels (values #f #f)) ((or space-preserve? (srl:mem-pred ; at least a single text node (lambda (node) (not (pair? node))) content)) ; No indent on this level, possible indent on nested levels (values #f indentation)) (else (values (cons srl:newline indentation) (cons (car indentation) indentation))))) (lambda (indent-here indent4recursive) (begin (for-each ; display content (if indent-here (lambda (kid) (begin (for-each (lambda (x) (display x port)) indent-here) (srl:display-node-out-recursive kid port method ns-prefix-assig namespace-assoc declared-ns-prefixes indent4recursive space-preserve? cdata-section-elements text-node-handler))) (lambda (kid) (srl:display-node-out-recursive kid port method ns-prefix-assig namespace-assoc declared-ns-prefixes indent4recursive space-preserve? cdata-section-elements text-node-handler))) content) (if indent-here (begin (display srl:newline port) (for-each (lambda (x) (display x port)) (cdr indentation)))) (for-each (lambda (x) (display x port)) end-tag)))))))))))))
Conventional namespace prefix referred to in XML-related specifications These prefixes are used for serializing the corresponding namespace URIs by default, unless a different prefix is supplied
(define srl:conventional-ns-prefixes '((dc . "http://purl.org/dc/elements/1.1/") (fo . "http://www.w3.org/1999/XSL/Format") (rdf . "http://www.w3.org/1999/02/22-rdf-syntax-ns#") (rng . "http://relaxng.org/ns/structure/1.0") (xlink . "http://www.w3.org/1999/xlink") (xqx . "http://www.w3.org/2005/XQueryX") (xsd . "http://www.w3.org/2001/XMLSchema") (xsi . "http://www.w3.org/2001/XMLSchema-instance") (xsl . "http://www.w3.org/1999/XSL/Transform")))
Returns (listof <namespace-assoc>) for the given SXML element
(define (srl:namespace-assoc-for-elem elem) ((srl:select-kids (lambda (node) (pair? node))) ((srl:select-kids (lambda (node) (and (pair? node) (eq? (car node) '*NAMESPACES*)))) (append ((srl:select-kids ; compatibility with SXML 3.0 (lambda (node) (and (pair? node) (eq? (car node) '@)))) ((srl:select-kids (lambda (node) (and (pair? node) (eq? (car node) '@)))) elem)) ((srl:select-kids ; compatibility with SXML 2.X (lambda (node) (and (pair? node) (eq? (car node) '@@)))) elem)))))
Returns (listof <namespace-assoc>) for the SXML document node
(define (srl:ns-assoc-for-top doc) ((srl:select-kids (lambda (node) (pair? node))) ((srl:select-kids (lambda (node) (and (pair? node) (eq? (car node) '*NAMESPACES*)))) ((srl:select-kids (lambda (node) ; After sequence normalization [1], the SXML 3.0 aux-list is used ; at the top-level (and (pair? node) (eq? (car node) '@)))) doc))))
Extract original prefix-binding from `namespace-assoc-lst' namespace-assoc-lst ::= (listof <namespace-assoc>) <namespace-assoc> ::= ( <namespace-id> "URI" original-prefix? ) Returns: (listof (cons original-prefix "URI"))
(define (srl:extract-original-prefix-binding namespace-assoc-lst) (map (lambda (triple) (cons (caddr triple) (cadr triple))) (filter ; specifies original prefix (lambda (memb) (= (length memb) 3)) namespace-assoc-lst)))
Returns the new value of `space-preserve?' in accordance with the value of xml:space attribute probably presented for the given SXML element `elem' space-preserve? ::= #t | #f - whether the SXML subtree inherits the xml:space attribute with the value "preserve"
(define (srl:update-space-specifier elem space-preserve?) (let ((xml-space-val ((srl:select-kids string?) ((srl:select-kids (lambda (node) (and (pair? node) (eq? (car node) 'xml:space)))) ((srl:select-kids (lambda (node) (and (pair? node) (eq? (car node) '@)))) elem))))) (cond ((null? xml-space-val) ; no xml:space attribute space-preserve?) ((string=? (car xml-space-val) "preserve") #t) ((string=? (car xml-space-val) "default") #f) (else space-preserve?))))
Returns #f if a given character `ch' is in XML character range [2] Otherwise, returns a string representing the character reference for that character
(define (srl:xml-char-escaped ch) (let ((code (char->integer ch))) (if (or (= code 9) (= code 10) (= code 13) (and (>= code 32) (<= code 55295)) (and (>= code 57344) (<= code 65533)) (>= code 65536)) #f (string-append "&#" (number->string code) ";" ))))
Represents a given string `str' as a CDATA section
(define (srl:string->cdata-section str) (let ((flush-buffer ; If a `buffer' is non-empty, converts it to a CDATA string and ; cons'es this string to `res'. Returns a new res (lambda (buffer res) (if (null? buffer) res (cons (string-append "<![CDATA[" (list->string (reverse buffer)) "]]>") res))))) (let loop ((src (string->list str)) (buffer '()) (res '(""))) (cond ((null? src) (srl:apply-string-append (reverse (flush-buffer buffer res)))) ((srl:xml-char-escaped (car src)) => (lambda (charref) (loop (cdr src) '() (cons charref (flush-buffer buffer res))))) ((and (char=? (car src) #\]) (not (null? buffer)) (char=? (car buffer) #\])) (loop (cdr src) '() (cons (string (car buffer) (car src)) ;= "]]" (flush-buffer (cdr buffer) res)))) (else ; any other character (loop (cdr src) (cons (car src) buffer) res))))))
Associative lists of characters to be escaped in XML character data and attribute values respectively [2]
(define srl:escape-alist-char-data '((#\& . "&") (#\< . "<") (#\> . ">")))
(define srl:escape-alist-att-value (append `((#\' . "'") (#\" . """) ; Escaping the newline character in attribute value (,srl:char-nl . " ")) srl:escape-alist-char-data))
(define srl:escape-alist-html-att '((#\& . "&") (#\> . ">") (#\' . "'") (#\" . """)))
Escape a string with the `srl:xml-char-escaped' and with the `escape-alist' supplied escape-alist ::= (listof (cons char string)) html-method? ::= #t | #f Returns the escaped string
(define (srl:string->escaped str escape-alist html-method?) (let loop ((src (string->list str)) (adj-chars '()) (res '())) (cond ((null? src) (srl:apply-string-append (reverse (cons (list->string (reverse adj-chars)) res)))) ((assv (car src) escape-alist) ; current character matches the alist => (lambda (pair) (if ; Subsect. 7.2 in [1]: ; "The HTML output method MUST NOT escape a & character occurring ; in an attribute value immediately followed by a { character" (and (char=? (car src) #\&) html-method? (not (null? (cdr src))) (char=? (cadr src) #\{)) (loop (cdr src) (cons (car src) adj-chars) res) (loop (cdr src) '() (cons (cdr pair) (cons (list->string (reverse adj-chars)) res)))))) ((srl:xml-char-escaped (car src)) => (lambda (esc) (loop (cdr src) '() (cons esc (cons (list->string (reverse adj-chars)) res))))) (else (loop (cdr src) (cons (car src) adj-chars) res)))))
(define (srl:string->char-data str) (srl:string->escaped str srl:escape-alist-char-data #f))
(define (srl:string->att-value str) (srl:string->escaped str srl:escape-alist-att-value #f))
(define (srl:string->html-att str) (srl:string->escaped str srl:escape-alist-html-att #t))
"..SHTML adds a special & syntax for non-ASCII (or non-Extended-ASCII) characters. The syntax is (& val), where val is a symbol or string naming with the symbolic name of the character, or an integer with the numeric value of the character." [3] entity ::= `(& ,val) val ::= symbol | string | number Returns the string representation for the entity
(define (srl:shtml-entity->char-data entity) ; TODO: think of an appropriate error message for an ill-formed entity (if (= (length entity) 2) (let ((val (cadr entity))) (cond ((symbol? val) (string-append "&" (symbol->string val) ";") ) ((string? val) (string-append "&" val ";") ) ((and (number? val) (integer? val) (> val 0)) ; to guarantee well-formedness of the result produced (string-append "&#" (number->string val) ";") ) (else ; should signal of an error ""))) ""))
Returns the list of strings that constitute the serialized representation for the attribute. Inserts a whitespace symbol in the beginning method ::= 'xml | 'html
(define (srl:attribute->str-lst prefix-string local-part att-value method) (let ((attval (srl:atomic->string att-value))) (cond (prefix-string (list " " prefix-string ":" local-part "=\"" ((if (eq? method 'html) srl:string->html-att srl:string->att-value) attval) "\"")) ((eq? method 'html) (if (string=? local-part attval) ; boolean attribute (list " " local-part) (list " " local-part "=\"" (srl:string->html-att attval) "\""))) (else ; unprefixed attribute, XML output method (list " " local-part "=\"" (srl:string->att-value attval) "\"")))))
Returns the list of strings that constitute the serialized representation for the namespace declaration. Inserts a whitespace symbol in the beginning ATTENTION: character escaping for namespace URI may be improper, study this issue
(define (srl:namespace-decl->str-lst prefix-string namespace-uri) (list " xmlns:" prefix-string "=\"" (srl:string->att-value namespace-uri) "\""))
According to SXML specification, <comment> ::= ( *COMMENT* "comment string" ) ATTENTION: in the case of ill-formed comment, should probably report an error instead of recovering
(define (srl:comment->str-lst comment-node) (let ((proper-string-in-comment? ; Whether a proper string occurs in the comment node. Thus, ; "For compatibility, the string '--' (double-hyphen) MUST NOT occur ; within comments. ... Note that the grammar does not allow a comment ; ending in --->." [2] (lambda (str) (let ((lng (string-length str))) (or (zero? lng) ; empty string allowed in comment [2] (and (not (char=? (string-ref str 0) #\-)) (let iter ((i 1) (prev-hyphen? #f)) (cond ((>= i lng) (not prev-hyphen?) ; string must not end with hyphen ) ((char=? (string-ref str i) #\-) (if prev-hyphen? #f (iter (+ i 1) #t))) (else (iter (+ i 1) #f)))))))))) (if (and (= (length comment-node) 2) (string? (cadr comment-node)) (proper-string-in-comment? (cadr comment-node))) (list "<!--" (cadr comment-node) "-->") (list "<!--" "-->") ; should probably report of an error )))
According to SXML specification, <PI> ::= ( *PI* pi-target <annotations>? "processing instruction content string" ) method ::= 'xml | 'html Subsect 7.3 in [1]: "The HTML output method MUST terminate processing instructions with > rather than ?>." ATTENTION: in the case of ill-formed PI content string, should probably report an error instead of recovering
(define (srl:processing-instruction->str-lst pi-node method) (let ((string-not-contain-charlist? ; Whether `str' does not contain a sequence of characters from ; `char-lst' as its substring (lambda (str char-lst) (let ((lng (string-length str))) (or (zero? lng) ; empty string doesn't contain (let iter ((i 0) (pattern char-lst)) (cond ((>= i lng) #t) ((char=? (string-ref str i) (car pattern)) (if (null? (cdr pattern)) ; it is the last member #f ; contains (iter (+ i 1) (cdr pattern)))) (else (iter (+ i 1) char-lst))))))))) (if (or (null? (cdr pi-node)) (not (symbol? (cadr pi-node)))) ; no target => ill-formed PI '() ; should probably raise an error (let ((content (filter string? (cddr pi-node)))) (cond ((null? content) ; PI with no content - correct situation (list "<?" (symbol->string (cadr pi-node)) (if (eq? method 'html) ">" "?>"))) ; Subsect. 7.3 in [1]: "It is a serialization error to use the HTML ; output method when > appears within a processing instruction in ; the data model instance being serialized." ((and (null? (cdr content)) ; only a single member (string-not-contain-charlist? (car content) (if (eq? method 'html) '(#\>) '(#\? #\>)))) (list "<?" (symbol->string (cadr pi-node)) " " (car content) (if (eq? method 'html) ">" "?>"))) (else ; should probably signal of an error '()))))))
Returns: (values prefix-string namespace-uri local-part declaration-required?) prefix-string - namespace prefix to be given to the serialized name: a string or #f if no prefix is required namespace-uri - the namespace URI for the given `name', #f if the name has no namespace URI local-part - local part of the name declaration-required ::= #t | #f - whether `prefix' has to be declared
(define (srl:name->qname-components name ns-prefix-assig namespace-assoc declared-ns-prefixes) (let ((use-ns-id-or-generate-prefix (lambda (ns-id) (if (and ns-id ; try to use namespace-id as a prefix (not (assq (string->symbol ns-id) ns-prefix-assig)) (not (assoc ns-id declared-ns-prefixes))) ns-id ; Otherwise - generate unique prefix ; Returns a prefix-string not presented in ns-prefix-assig and ; declared-ns-prefixes (let loop ((i 1)) (let ((candidate (string-append "prfx" (number->string i)))) (if (or (assoc candidate declared-ns-prefixes) (assq (string->symbol candidate) ns-prefix-assig)) (loop (+ i 1)) candidate)))))) (n-parts (srl:split-name name))) (cond ((not (car n-parts)) ; no namespace-id => no namespace (values #f #f (cdr n-parts) ; name as a string #f)) ((string-ci=? (car n-parts) "xml") ; reserved XML namespace (values (car n-parts) "http://www.w3.org/XML/1998/namespace" (cdr n-parts) #f)) (else (call-with-values (lambda () (cond ((assq (string->symbol (car n-parts)) ; suppose a namespace-id namespace-assoc) => (lambda (lst) (values (cadr lst) (car n-parts)))) (else ; first part of a name is a namespace URI (values (car n-parts) #f)))) (lambda (namespace-uri ns-id) (cond ((srl:assoc-cdr-string= namespace-uri declared-ns-prefixes) => (lambda (pair) ; Prefix for that namespace URI already declared (values (car pair) namespace-uri (cdr n-parts) #f))) (else ; namespace undeclared (values (cond ((srl:assoc-cdr-string= namespace-uri ns-prefix-assig) => (lambda (pair) ; A candidate namespace prefix is supplied from the user (let ((candidate (symbol->string (car pair)))) (if (assoc candidate declared-ns-prefixes) ; The prefix already bound to a different namespace ; Avoid XML prefix re-declaration (use-ns-id-or-generate-prefix ns-id) candidate)))) (else (use-ns-id-or-generate-prefix ns-id))) namespace-uri (cdr n-parts) #t ; in any case, prefix declaration is required )))))))))
Constructs start and end tags for an SXML element `elem' method ::= 'xml | 'html Returns: (values start-tag end-tag ns-prefix-assig namespace-assoc declared-ns-prefixes) start-tag ::= (listof string) end-tag ::= (listof string) or #f for empty element TODO: escape URI attributes for HTML TODO: indentation probably should be made between attribute declarations
(define (srl:construct-start-end-tags elem method ns-prefix-assig namespace-assoc declared-ns-prefixes) (let ((ns-assoc-here (srl:namespace-assoc-for-elem elem)) (empty? (srl:empty-elem? elem))) (let ((ns-prefix-assig (append (srl:extract-original-prefix-binding ns-assoc-here) ns-prefix-assig)) (namespace-assoc (append ns-assoc-here namespace-assoc))) (call-with-values (lambda () (srl:name->qname-components ; element name (car elem) ns-prefix-assig namespace-assoc declared-ns-prefixes)) (lambda (elem-prefix elem-uri elem-local elem-decl-required?) (let loop ((attrs (reverse ((srl:select-kids (lambda (node) ; not SXML 3.0 aux-list (and (pair? node) (not (eq? (car node) '@))))) ((srl:select-kids (lambda (node) (and (pair? node) (eq? (car node) '@)))) elem)))) (start-tag (if (or (not empty?) (and (eq? method 'html) (not elem-prefix) (srl:member-ci elem-local ; ATTENTION: should probably move this list ; to a global const '("area" "base" "basefont" "br" "col" "frame" "hr" "img" "input" "isindex" "link" "meta" "param")))) '(">") '("/>"))) (ns-prefix-assig ns-prefix-assig) (namespace-assoc namespace-assoc) (declared-ns-prefixes ; As if element namespace already declared (if elem-decl-required? (cons (cons elem-prefix elem-uri) declared-ns-prefixes) declared-ns-prefixes))) (if (null? attrs) ; attributes scanned (let ((elem-name (srl:qname->string elem-prefix elem-local))) (values (cons "<" (cons elem-name (if elem-decl-required? (cons (srl:namespace-decl->str-lst elem-prefix elem-uri) start-tag) start-tag))) (if empty? #f (list "</" elem-name ">")) ns-prefix-assig namespace-assoc declared-ns-prefixes)) (call-with-values (lambda () (srl:name->qname-components (caar attrs) ; attribute name ns-prefix-assig namespace-assoc declared-ns-prefixes)) (lambda (attr-prefix attr-uri attr-local attr-decl-required?) (let ((start-tag (cons (srl:attribute->str-lst attr-prefix attr-local ; TODO: optimize for HTML output method (if (null? (cdar attrs)) ; no attribute value attr-local (cadar attrs)) method) start-tag))) (loop (cdr attrs) (if attr-decl-required? (cons (srl:namespace-decl->str-lst attr-prefix attr-uri) start-tag) start-tag) ns-prefix-assig namespace-assoc (if attr-decl-required? (cons (cons attr-prefix attr-uri) declared-ns-prefixes) declared-ns-prefixes))))))))))))
Creates the serialized representation for the XML declaration Returns: (listof string) version ::= string | number standalone ::= 'yes | 'no | 'omit
(define (srl:make-xml-decl version standalone) (let ((version (if (number? version) (number->string version) version))) (if (eq? standalone 'omit) (list "<?xml version='" version "'?>") (list "<?xml version='" version "' standalone='" (symbol->string standalone) "'?>"))))
omit-xml-declaration? ::= #t | #f standalone ::= 'yes | 'no | 'omit version ::= string | number
(define (srl:top->nested-str-lst doc cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone version) (let* ((namespace-assoc (srl:ns-assoc-for-top doc)) (ns-prefix-assig (append (srl:extract-original-prefix-binding namespace-assoc) ns-prefix-assig)) (serialized-content (map (if indent ; => output each member from the newline (let ((indentation (list indent))) ; for nested elements (lambda (kid) (list srl:newline (srl:node->nested-str-lst-recursive kid method ns-prefix-assig namespace-assoc '() indentation #f cdata-section-elements srl:string->char-data)))) (lambda (kid) (srl:node->nested-str-lst-recursive kid method ns-prefix-assig namespace-assoc '() indent #f cdata-section-elements srl:string->char-data))) ((srl:select-kids ; document node content (lambda (node) ; TODO: support SXML entities (not (and (pair? node) (memq (car node) '(@ @@ *ENTITY*)))))) doc)))) (if (or (eq? method 'html) omit-xml-declaration?) (if (and indent (not (null? serialized-content))) ; Remove the starting newline ; ATTENTION: beware of `Gambit cadar bug': ; http://mailman.iro.umontreal.ca/pipermail/gambit-list/ ; 2005-July/000315.html (cons (cadar serialized-content) (cdr serialized-content)) serialized-content) (list (srl:make-xml-decl version standalone) serialized-content))))
(define (srl:display-top-out doc port cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone version) (let ((no-xml-decl? ; no XML declaration was displayed? (if (not (or (eq? method 'html) omit-xml-declaration?)) (begin (for-each ; display xml declaration (lambda (x) (display x port)) (srl:make-xml-decl version standalone)) #f) #t)) (content ; document node content ((srl:select-kids (lambda (node) ; TODO: support SXML entities (not (and (pair? node) (memq (car node) '(@ @@ *ENTITY*)))))) doc)) (namespace-assoc (srl:ns-assoc-for-top doc))) (let ((ns-prefix-assig (append (srl:extract-original-prefix-binding namespace-assoc) ns-prefix-assig))) (cond ((null? content) ; generally a rare practical situation #t) ; nothing more to do ((and indent no-xml-decl?) ; We'll not display newline before (car content) (let ((indentation (list indent))) ; for nested elements (for-each (lambda (kid put-newline?) (begin (if put-newline? (display srl:newline port)) (srl:display-node-out-recursive kid port method ns-prefix-assig namespace-assoc '() indentation #f cdata-section-elements srl:string->char-data))) content ; After sequence normalization, content does not contain #f (cons #f (cdr content))))) (else (for-each (if indent ; => output each member from the newline (let ((indentation (list indent))) ; for nested elements (lambda (kid) (begin (display srl:newline port) (srl:display-node-out-recursive kid port method ns-prefix-assig namespace-assoc '() indentation #f cdata-section-elements srl:string->char-data)))) (lambda (kid) (srl:display-node-out-recursive kid port method ns-prefix-assig namespace-assoc '() indent #f cdata-section-elements srl:string->char-data))) content))))))
Returns a string that contains the serialized representation for `sxml-obj'. cdata-section-elements ::= (listof sxml-name) indent ::= #t | #f | whitespace-string method = 'xml | 'html ns-prefix-assign ::= (listof (cons prefix-symbol namespace-uri-string)) omit-xml-declaration? ::= #t | #f standalone ::= 'yes | 'no | 'omit version ::= number | string
(define (srl:sxml->string sxml-obj cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone version) (srl:apply-string-append (srl:clean-fragments (srl:top->nested-str-lst (srl:normalize-sequence sxml-obj) cdata-section-elements (if (and indent (not (string? indent))) " " indent) method ns-prefix-assig omit-xml-declaration? standalone version))))
Writes the serialized representation of the `sxml-obj' to an output port `port'. The result returned by the function is unspecified.
(define (srl:display-sxml sxml-obj port-or-filename cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone version) (if (string? port-or-filename) ; a filename? (let ((out (open-output-file port-or-filename))) (begin (srl:display-top-out (srl:normalize-sequence sxml-obj) out cdata-section-elements (if (and indent (not (string? indent))) " " indent) method ns-prefix-assig omit-xml-declaration? standalone version) (display srl:newline out) ; newline at the end of file (close-output-port out))) (srl:display-top-out (srl:normalize-sequence sxml-obj) port-or-filename cdata-section-elements (if (and indent (not (string? indent))) " " indent) method ns-prefix-assig omit-xml-declaration? standalone version)))
procedure srl:parameterizable :: SXML-OBJ [PORT] {PARAM}* -> -> STRING|unspecified sxml-obj - an SXML object to serialize param ::= (cons param-name param-value) param-name ::= symbol 1. cdata-section-elements value ::= (listof sxml-elem-name) sxml-elem-name ::= symbol 2. indent value ::= 'yes | #t | 'no | #f | whitespace-string 3. method value ::= 'xml | 'html 4. ns-prefix-assig value ::= (listof (cons prefix namespace-uri)) prefix ::= symbol namespace-uri ::= string 5. omit-xml-declaration? value ::= 'yes | #t | 'no | #f 6. standalone value ::= 'yes | #t | 'no | #f | 'omit 7. version value ::= string | number ATTENTION: If a parameter name is unexpected or a parameter value is ill-formed, the parameter is silently ignored. Probably, a warning message in such a case would be more appropriate. Example: (srl:parameterizable '(tag (@ (attr "value")) (nested "text node") (empty)) (current-output-port) '(method . xml) ; XML output method is used by default '(indent . "\t") ; use a single tabulation to indent nested elements '(omit-xml-declaration . #f) ; add XML declaration '(standalone . yes) ; denote a standalone XML document '(version . "1.0")) ; XML version
(define (srl:parameterizable sxml-obj . port-or-filename+params) (call-with-values (lambda () (if (and (not (null? port-or-filename+params)) (or (output-port? (car port-or-filename+params)) (string? (car port-or-filename+params)))) (values (car port-or-filename+params) (cdr port-or-filename+params)) (values #f port-or-filename+params))) (lambda (port-or-filename params) (let loop ((params params) (cdata-section-elements '()) (indent " ") (method 'xml) (ns-prefix-assig srl:conventional-ns-prefixes) (omit-xml-declaration? #t) (standalone 'omit) (version "1.0")) (cond ((null? params) ; all parameters parsed (if port-or-filename (srl:display-sxml sxml-obj port-or-filename cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone version) (srl:sxml->string sxml-obj cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone version))) ((or (not (pair? (car params))) ; not a pair or has no param value (null? (cdar params))) (loop (cdr params) cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone version)) (else (let ((prm-value (cdar params))) (case (caar params) ((cdata-section-elements) (loop (cdr params) (if (list? prm-value) prm-value cdata-section-elements) indent method ns-prefix-assig omit-xml-declaration? standalone version)) ((indent) (loop (cdr params) cdata-section-elements (cond ((boolean? prm-value) (if prm-value " " prm-value)) ((string? prm-value) prm-value) ((eq? prm-value 'yes) " ") ((eq? prm-value 'no) #f) (else indent)) method ns-prefix-assig omit-xml-declaration? standalone version)) ((method) (loop (cdr params) cdata-section-elements indent (if (or (eq? prm-value 'xml) (eq? prm-value 'html)) prm-value method) ns-prefix-assig omit-xml-declaration? standalone version)) ((ns-prefix-assig) (loop (cdr params) cdata-section-elements indent method (if (and (list? prm-value) (not (srl:mem-pred ; no non-pair members (lambda (x) (not (pair? x))) prm-value))) (append prm-value ns-prefix-assig) ns-prefix-assig) omit-xml-declaration? standalone version)) ((omit-xml-declaration) (loop (cdr params) cdata-section-elements indent method ns-prefix-assig (cond ((boolean? prm-value) prm-value) ((eq? prm-value 'yes) #t) ((eq? prm-value 'no) #f) (else indent)) standalone version)) ((standalone) (loop (cdr params) cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? (cond ((memv prm-value '(yes no omit)) prm-value) ((boolean? prm-value) (if prm-value 'yes 'no)) (else standalone)) version)) ((version) (loop (cdr params) cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone (if (or (string? prm-value) (number? prm-value)) prm-value version))) (else (loop (cdr params) cdata-section-elements indent method ns-prefix-assig omit-xml-declaration? standalone version))))))))))
procedure srl:sxml->xml :: SXML-OBJ [PORT-OR-FILENAME] -> STRING|unspecified Serializes the `sxml-obj' into XML, with indentation to facilitate readability by a human. sxml-obj - an SXML object (a node or a nodeset) to be serialized port-or-filename - an output port or an output file name, an optional argument If `port-or-filename' is not supplied, the functions return a string that contains the serialized representation of the `sxml-obj'. If `port-or-filename' is supplied and is a port, the functions write the serialized representation of `sxml-obj' to this port and return an unspecified result. If `port-or-filename' is supplied and is a string, this string is treated as an output filename, the serialized representation of `sxml-obj' is written to that filename and an unspecified result is returned. If a file with the given name already exists, the effect is unspecified.
(define (srl:sxml->xml sxml-obj . port-or-filename) (if (null? port-or-filename) (srl:sxml->string sxml-obj '() #t 'xml srl:conventional-ns-prefixes #t 'omit "1.0") (srl:display-sxml sxml-obj (car port-or-filename) '() #t 'xml srl:conventional-ns-prefixes #t 'omit "1.0")))
procedure srl:sxml->xml-noindent :: SXML-OBJ [PORT-OR-FILENAME] -> -> STRING|unspecified Serializes the `sxml-obj' into XML, without indentation.
(define (srl:sxml->xml-noindent sxml-obj . port-or-filename) (if (null? port-or-filename) (srl:sxml->string sxml-obj '() #f 'xml srl:conventional-ns-prefixes #t 'omit "1.0") (srl:display-sxml sxml-obj (car port-or-filename) '() #f 'xml srl:conventional-ns-prefixes #t 'omit "1.0")))
procedure srl:sxml->html :: SXML-OBJ [PORT-OR-FILENAME] -> STRING|unspecified Serializes the `sxml-obj' into HTML, with indentation to facilitate readability by a human. sxml-obj - an SXML object (a node or a nodeset) to be serialized port-or-filename - an output port or an output file name, an optional argument If `port-or-filename' is not supplied, the functions return a string that contains the serialized representation of the `sxml-obj'. If `port-or-filename' is supplied and is a port, the functions write the serialized representation of `sxml-obj' to this port and return an unspecified result. If `port-or-filename' is supplied and is a string, this string is treated as an output filename, the serialized representation of `sxml-obj' is written to that filename and an unspecified result is returned. If a file with the given name already exists, the effect is unspecified.
(define (srl:sxml->html sxml-obj . port-or-filename) (if (null? port-or-filename) (srl:sxml->string sxml-obj '() #t 'html '() #t 'omit "4.0") (srl:display-sxml sxml-obj (car port-or-filename) '() #t 'html '() #t 'omit "4.0")))
procedure srl:sxml->html-noindent :: SXML-OBJ [PORT-OR-FILENAME] -> -> STRING|unspecified Serializes the `sxml-obj' into HTML, without indentation.
(define (srl:sxml->html-noindent sxml-obj . port-or-filename) (if (null? port-or-filename) (srl:sxml->string sxml-obj '() #f 'html '() #t 'omit "4.0") (srl:display-sxml sxml-obj (car port-or-filename) '() #f 'html '() #t 'omit "4.0")))


|
|||||||||
| PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
See:
Description
| Interface Summary | |
|---|---|
| RNSClient | RNSClient object is generated by RNSClientHome.getRNSClient() . |
| RNSExtensionClient | RNSExtensionClient object is generated by
RNSClientHome.getRNSExtensionClient() . |
| RNSIterator<E> | Iterator interface for List and Search operations. |
| RNSRecursiveListener | Callback interface for recursive operations. |
| RNSSearchClient | RNSSearchClient object is generated by
RNSClientHome.getRNSSearchClient() . |
| Class Summary | |
|---|---|
| BaseClient | Web service client APIs for Globus. |
| DirnameBasename | Divided pathname into dirname and basename. |
| GlobusURLFixed | Extend and modify org.globus.util.GlobusURL |
| GridFTPUtil | Utilities for FTP and GridFTP client. |
| RNSAddHandle | Handle for preparation of bulk Add operation. |
| RNSClientHome | Interpret command options and Initialize RNS client environments. |
| RNSClientImpl | RNSClient implementation. |
| RNSDirent | Represent a RNS directory. |
| RNSDirentComparator | Comparator for RNSDirent. |
| RNSDirHandle | Handle to get an entry. |
| RNSExtensionClientImpl | RNSExtensionClient implementation. |
| RNSKeyValue | Key/Value operations to RNS Metadata. |
| RNSListIterator | RNS list operation client to access WS-Iterator service. |
| RNSPortTypeCache | Cache response data of RNS operations (Lookup, GetMultipleResourceProperties) (Directory cache). |
| RNSSearchClientImpl | RNSSearchClientImpl implementation. |
| RNSSearchResult | A result data structure of RNS search. |
| RNSSearchResultHandle | Handle for results of Search operation. |
| RNSStat | Structure for RNS directory properties. |
| Enum Summary | |
|---|---|
| RNSDirent.TYPE | Entry types. |
| RNSDirentComparator.MODE | Sorting modes. |
| RNSError.Errno | Error types and messages. |
| Exception Summary | |
|---|---|
| RNSError | RNS errors. |
RNS client APIs.
|
|||||||||
| PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |


{% extends "layout.html" %} {% set title = 'CoolProp: Fluid properties for the masses' %} {% block body %}
CoolProp is an open-source, cross-platform, free property database based in C++ that includes pure fluids, pseudo-pure fluids, and humid air properties.
To get CoolProp head to Downloads or check out the examples
Changelog is here
Documentation is here
C++ documentation (doxygen) is here
As of February 2014, 114 pure and pseudo-pure fluids are included as well as 50 incompressible liquids.
If you have found a problem with CoolProp, please file a ticket at CoolProp support ticket and we will do our best for a speedy response (usually less than 24 hours)
You can also join the Google group<EMAIL_ADDRESS>Ian Bell , Sylvain Quoilin , Vincent Lemort , University of Liege, Liege, Belgium
Jorrit Wronski , Technical University of Denmark, Kgs. Lyngby, Denmark


Dock Widgets Example
The application presents a simple business letter template, and has a list of customer names and addresses and a list of standard phrases in two dock windows. The user can click a customer to have their name and address inserted into the template, and click one or more of the standard phrases. Errors can be corrected by clicking the Undo button. Once the letter has been prepared it can be printed or saved as HTML.
MainWindow Class Definition
Here's the class definition:
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); private slots: void newLetter(); void save(); void print(); void undo(); void about(); void insertCustomer(const QString &customer); void addParagraph(const QString ¶graph); private: void createActions(); void createStatusBar(); void createDockWindows(); QTextEdit *textEdit; QListWidget *customerList; QListWidget *paragraphsList; QMenu *viewMenu; };
We will now review each function in turn.
MainWindow Class Implementation
#include <QtWidgets> #if defined(QT_PRINTSUPPORT_LIB) #include <QtPrintSupport/qtprintsupportglobal.h> #if QT_CONFIG(printdialog) #include <QtPrintSupport> #endif #endif #include "mainwindow.h"
We start by including <QtWidgets>
, a header file that contains the definition of all classes in the Qt Core, Qt GUI and Qt Widgets modules. This saves us from having to include every class individually and is especially convenient if we add new widgets. We also include mainwindow.h
.
MainWindow::MainWindow() : textEdit(new QTextEdit) { setCentralWidget(textEdit); createActions(); createStatusBar(); createDockWindows(); setWindowTitle(tr("Dock Widgets")); newLetter(); setUnifiedTitleAndToolBarOnMac(true); }
In the constructor, we start by creating a QTextEdit widget. Then we call QMainWindow::setCentralWidget(). This function passes ownership of the QTextEdit to the MainWindow
and tells the MainWindow
that the QTextEdit will occupy the MainWindow
's central area.
Then we call createActions()
, createMenus()
, createToolBars()
, createStatusBar()
, and createDockWindows()
to set up the user interface. Finally we call setWindowTitle()
to give the application a title, and newLetter()
to create a new letter template.
We won't quote the createActions()
, createMenus()
, createToolBars()
, and createStatusBar()
functions since they follow the same pattern as all the other Qt examples.
void MainWindow::createDockWindows() { QDockWidget *dock = new QDockWidget(tr("Customers"), this); dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); customerList = new QListWidget(dock); customerList->addItems(QStringList() << "John Doe, Harmony Enterprises, 12 Lakeside, Ambleton" << "Jane Doe, Memorabilia, 23 Watersedge, Beaton" << "Tammy Shea, Tiblanka, 38 Sea Views, Carlton" << "Tim Sheen, Caraba Gifts, 48 Ocean Way, Deal" << "Sol Harvey, Chicos Coffee, 53 New Springs, Eccleston" << "Sally Hobart, Tiroli Tea, 67 Long River, Fedula"); dock->setWidget(customerList); addDockWidget(Qt::RightDockWidgetArea, dock); viewMenu->addAction(dock->toggleViewAction()); dock = new QDockWidget(tr("Paragraphs"), this); paragraphsList = new QListWidget(dock); paragraphsList->addItems(QStringList() << "Thank you for your payment which we have received today." << "Your order has been dispatched and should be with you " "within 28 days." << "We have dispatched those items that were in stock. The " "rest of your order will be dispatched once all the " "remaining items have arrived at our warehouse. No " "additional shipping charges will be made." << "You made a small overpayment (less than $5) which we " "will keep on account for you, or return at your request." << "You made a small underpayment (less than $1), but we have " "sent your order anyway. We'll add this underpayment to " "your next bill." << "Unfortunately you did not send enough money. Please remit " "an additional $.  << "You made an overpayment (more than $5). Do you wish to " "buy more items, or should we return the excess to you?"); dock->setWidget(paragraphsList); addDockWidget(Qt::RightDockWidgetArea, dock); viewMenu->addAction(dock->toggleViewAction()); connect(customerList, &QListWidget::currentTextChanged, this, &MainWindow::insertCustomer); connect(paragraphsList, &QListWidget::currentTextChanged, this, &MainWindow::addParagraph); }
We create the customers dock window first, and in addition to a window title, we also pass it a this
pointer so that it becomes a child of MainWindow
. Normally we don't have to pass a parent because widgets are parented automatically when they are laid out: but dock windows aren't laid out using layouts.
We've chosen to restrict the customers dock window to the left and right dock areas. (So the user cannot drag the dock window to the top or bottom dock areas.) The user can drag the dock window out of the dock areas entirely so that it becomes a free floating window. We can change this (and whether the dock window is moveable or closable) using QDockWidget::setFeatures().
Once we've created the dock window we create a list widget with the dock window as parent, then we populate the list and make it the dock window's widget. Finally we add the dock widget to the MainWindow
using addDockWidget()
, choosing to put it in the right dock area.
We undertake a similar process for the paragraphs dock window, except that we don't restrict which dock areas it can be dragged to.
Finally we set up the signal-slot connections. If the user clicks a customer or a paragraph their currentTextChanged()
signal will be emitted and we connect these to insertCustomer()
and addParagraph() passing the text that was clicked.
We briefly discuss the rest of the implementation, but have now covered everything relating to dock windows.
void MainWindow::newLetter() { textEdit->clear(); QTextCursor cursor(textEdit->textCursor()); cursor.movePosition(QTextCursor::Start); QTextFrame *topFrame = cursor.currentFrame(); QTextFrameFormat topFrameFormat = topFrame->frameFormat(); topFrameFormat.setPadding(16); topFrame->setFrameFormat(topFrameFormat); QTextCharFormat textFormat; QTextCharFormat boldFormat; boldFormat.setFontWeight(QFont::Bold); QTextCharFormat italicFormat; italicFormat.setFontItalic(true); QTextTableFormat tableFormat; tableFormat.setBorder(1); tableFormat.setCellPadding(16); tableFormat.setAlignment(Qt::AlignRight); cursor.insertTable(1, 1, tableFormat); cursor.insertText("The Firm", boldFormat); cursor.insertBlock(); cursor.insertText("321 City Street", textFormat); cursor.insertBlock(); cursor.insertText("Industry Park"); cursor.insertBlock(); cursor.insertText("Some Country"); cursor.setPosition(topFrame->lastPosition()); cursor.insertText(QDate::currentDate().toString("d MMMM yyyy"), textFormat); cursor.insertBlock(); cursor.insertBlock(); cursor.insertText("Dear ", textFormat); cursor.insertText("NAME", italicFormat); cursor.insertText(",", textFormat); for (int i = 0; i < 3; ++i) cursor.insertBlock(); cursor.insertText(tr("Yours sincerely,"), textFormat); for (int i = 0; i < 3; ++i) cursor.insertBlock(); cursor.insertText("The Boss", textFormat); cursor.insertBlock(); cursor.insertText("ADDRESS", italicFormat); }
In this function we clear the QTextEdit so that it is empty. Next we create a QTextCursor on the QTextEdit. We move the cursor to the start of the document and create and format a frame. We then create some character formats and a table format. We insert a table into the document and insert the company's name and address into a table using the table and character formats we created earlier. Then we insert the skeleton of the letter including two markers NAME
and ADDRESS
. We will also use the Yours sincerely,
text as a marker.
void MainWindow::insertCustomer(const QString &customer) { if (customer.isEmpty()) return; QStringList customerList = customer.split(", "); QTextDocument *document = textEdit->document(); QTextCursor cursor = document->find("NAME"); if (!cursor.isNull()) { cursor.beginEditBlock(); cursor.insertText(customerList.at(0)); QTextCursor oldcursor = cursor; cursor = document->find("ADDRESS"); if (!cursor.isNull()) { for (int i = 1; i < customerList.size(); ++i) { cursor.insertBlock(); cursor.insertText(customerList.at(i)); } cursor.endEditBlock(); } else oldcursor.endEditBlock(); } }
If the user clicks a customer we split the customer details into pieces. We then look for the NAME
marker using the find()
function. This function selects the text it finds, so when we call insertText()
with the customer's name the name replaces the marker. We then look for the ADDRESS
marker and replace it with each line of the customer's address. Notice that we wrapped all the insertions between a beginEditBlock()
and endEditBlock()
pair. This means that the entire name and address insertion is treated as a single operation by the QTextEdit, so a single undo will revert all the insertions.
void MainWindow::addParagraph(const QString ¶graph) { if (paragraph.isEmpty()) return; QTextDocument *document = textEdit->document(); QTextCursor cursor = document->find(tr("Yours sincerely,")); if (cursor.isNull()) return; cursor.beginEditBlock(); cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::MoveAnchor, 2); cursor.insertBlock(); cursor.insertText(paragraph); cursor.insertBlock(); cursor.endEditBlock(); }
This function works in a similar way to insertCustomer()
. First we look for the marker, in this case, Yours sincerely,
, and then replace it with the standard paragraph that the user clicked. Again we use a beginEditBlock()
... endEditBlock()
pair so that the insertion can be undone as a single operation.
void MainWindow::print() { #if QT_CONFIG(printdialog) QTextDocument *document = textEdit->document(); QPrinter printer; QPrintDialog dlg(&printer, this); if (dlg.exec() != QDialog::Accepted) { return; } document->print(&printer); statusBar()->showMessage(tr("Ready"), 2000); #endif }
Qt's QTextDocument class makes printing documents easy. We simply take the QTextEdit's QTextDocument, set up the printer and print the document.
void MainWindow::save() { QMimeDatabase mimeDatabase; QString fileName = QFileDialog::getSaveFileName(this, tr("Choose a file name"), ".", mimeDatabase.mimeTypeForName("text/html").filterString()); if (fileName.isEmpty()) return; QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("Dock Widgets"), tr("Cannot write file %1:\n%2.") .arg(QDir::toNativeSeparators(fileName), file.errorString())); return; } QTextStream out(&file); QApplication::setOverrideCursor(Qt::WaitCursor); out << textEdit->toHtml(); QApplication::restoreOverrideCursor(); statusBar()->showMessage(tr("Saved '%1'").arg(fileName), 2000); }
QTextEdit can output its contents in HTML format, so we prompt the user for the name of an HTML file and if they provide one we simply write the QTextEdit's contents in HTML format to the file.
void MainWindow::undo() { QTextDocument *document = textEdit->document(); document->undo(); }
If the focus is in the QTextEdit, pressing Ctrl+Z undoes as expected. But for the user's convenience we provide an application-wide undo function that simply calls the QTextEdit's undo: this means that the user can undo regardless of where the focus is in the application.
Files:
- mainwindows/dockwidgets/mainwindow.cpp
- mainwindows/dockwidgets/mainwindow.h
- mainwindows/dockwidgets/main.cpp
- mainwindows/dockwidgets/dockwidgets.pro
- mainwindows/dockwidgets/dockwidgets.qrc
Images:


Gravity is a light-weight Inversion-of-Control (IoC) / Dependency-Injection and configuration management framework.
The framework allows multiple ways of configuring the components via a plugin model and comes with a default Beanshell plugin.
This is a proxy-based solution that allows constructor-injection, method-injection and combo-injection (a combination of constructor- and method-injection techniques).
This is not an AOP solution and hence there is no built-in solution for interceptors or mixins; there are lots of other good frameworks for this. However, there is a hook to allow proxy-based AOP solutions (like dynaop) to be plugged-in, to weave the components.


CameraViewController
public class CameraViewController: UIViewController, UIPopoverPresentationControllerDelegate
Open camera to take photo. This view controller will include user guide info button, flash button and reverse camera button
-
title for info popover. Default to
How to Use
Declaration
Swift
public var infoTitle : String = "How to Use"
-
Default instruction on how to take photo
Declaration
Swift
public var infoTxt : String = "Snap a photo of an item you'd like to find, and we'll search our store to find a match or something very similar."
-
Tips for using camera button
Declaration
Swift
public var infoCameraTxt : String = "Photograph the item straight-on in bright lighting for the best search results."
-
Tips for using flash button
Declaration
Swift
public var infoFlashTxt : String = "Use the flash if there isn't enough light"
-
show/hide Power by ViSenze logo
Declaration
Swift
public var showPowerByViSenze : Bool = true
-
Camera view
Declaration
Swift
public let cameraView : CameraView =
-
camera button for taking photo
Declaration
Swift
public let cameraButton : UIButton =
-
close camera button. Default to back arrow icon
Declaration
Swift
public let closeButton : UIButton =
-
Info button. For showing user guide
Declaration
Swift
public let infoButton : UIButton =
-
Power by ViSenze
Declaration
Swift
public let powerView : UIImageView =
-
swap/reverse front and back camera button
Declaration
Swift
public let swapButton : UIButton =
-
select photo from library button
Declaration
Swift
public let libraryButton : UIButton =
-
turn on/off flash button
Declaration
Swift
public let flashButton : UIButton =
-
Constructor
- Parameters:
- croppingEnabled: enable/disable cropping after taking photo
- allowsLibraryAccess: whether to allow user select image from photo library
- completion: callback after taking photo / selecting photo from library
Declaration
Swift
public init(croppingEnabled: Bool, allowsLibraryAccess: Bool = true, completion: @escaping CameraViewCompletion)
Parameters
croppingEnabled
enable/disable cropping after taking photo
allowsLibraryAccess
whether to allow user select image from photo library
completion
callback after taking photo / selecting photo from library
- Parameters:
-
Undocumented
Declaration
Swift
public class CameraViewController: UIViewController, UIPopoverPresentationControllerDelegate
-
Undocumented
Declaration
Swift
public class CameraViewController: UIViewController, UIPopoverPresentationControllerDelegate
-
Undocumented
Declaration
Swift
public class CameraViewController: UIViewController, UIPopoverPresentationControllerDelegate
-
Configure the background of the superview to black and add the views on this superview. Then, request the update of constraints for this superview.
Declaration
Swift
public override func loadView()
-
Setup the constraints when the app is starting or rotating the screen. To avoid the override/conflict of stable constraint, these stable constraint are one time configurable. Any other dynamic constraint are configurable when the device is rotating, based on the device orientation.
Declaration
Swift
override public func updateViewConstraints()
-
Add observer to check when the camera has started, enable the volume buttons to take the picture, configure the actions of the buttons on the screen, check the permissions of access of the camera and the photo library. Configure the camera focus when the application start, to avoid any bluried image.
Declaration
Swift
public override func viewDidLoad()
-
Start the session of the camera.
Declaration
Swift
public override func viewWillAppear(_ animated: Bool)
-
Enable the button to take the picture when the camera is ready.
Declaration
Swift
public override func viewDidAppear(_ animated: Bool)
-
Update constraints during rotation
Declaration
Swift
override public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
-
important - this is needed so that a popover (info guide text) will be shown instead of fullscreen for ios 8.3+
Declaration
Swift
public func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle
-
return .none to display as popover (ios 8.0 - 8.2)
Declaration
Swift
public func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle
-
Open photo library to pick photo
Declaration
Swift
public class func imagePickerViewController(croppingEnabled: Bool, completion: @escaping CameraViewCompletion) -> UINavigationController


Authorizing an Unauthorized SuperUser
How to authorize an unauthorized SuperUser account using the SuperUser Accounts module.
- Navigate to Host > SuperUser Accounts.
- Click the Unauthorized link to display only unauthorized accounts and find the required account.
- Click the Edit button beside their record.
- Click the Authorize User link. This displays the message "User Successfully Authorized" and sets the Authorized field to True.


Currently, I'm a Data & Reporting Analyst with progressive experience in the banking
industry. I am interested in data science and using data to improve business decisions and
processes. I have experience using Python and Pandas for statistical analysis as well as experience
writing SQL queries. I love a good challenge and I'm always looking to acquire new skills and
knowledge. I have a Master's degree in Business Administration, a Bachelor's degree in Psychology,
and full stack developer experience. My education had provided a multi-discipline background,
exposing me to many different perspectives throughout my career. This has allowed me to develop
my communication skills and become more adaptable when looking for innovative ideas for
improvement.
Check out some projects I've worked on
Projects


Detects boolean expressions that can be safely simplified like
a || true
.
Does not simplify expressions if some side effects can be eliminated, such as
return || true
for example.


Ooooooooh!
There's going to be a raffle!
{% block content -%}{% endblock -%}
{% block bodyend -%}{% endblock -%}


Whooops! We can't access to your Web3 account!
Be sure to log in your chosen Web3 provider and authorize HIPR to connect to your account!
>
Back to Home


Your non-medical cannabis retail store application has been approved in principle.
After completing the required fields and paying your first-year licensing fee, your licence will be approved, and you can begin ordering product from the Liquor Distribution Branch.
As per your licence terms and conditions, you can only purchase your non-medical cannabis supply directly from the Liquor Distribution Branch. However, cannabis accessories may be obtained from other sources. Any cannabis you order must be securely received and locked at your store location. Please ensure you have adequate security in place prior to ordering.
Below you will find a checklist of requirements that an inspector will review at the time of your store inspection. It is your responsibility to ensure the requirements are met. Failure to meet these requirements could result in the temporary suspension of your licence.
Please see the Cannabis Retail Store Terms and Conditions handbook for more information.
The following physical security requirements are in place:
Security cameras with full unobstructed view of:
Proceed to pay online using a credit card through the secure web portal.


THE NIGHTMARE BEFORE CHRISTMAS A film review by James Berardinelli Copyright 1993 James Berardinelli
THE NIGHTMARE BEFORE CHRISTMAS
Rating (Linear 0 to 10): 6.7
Date Released: 10/22/93 Running Length: 1:15 Rated: PG (Cartoon-like monsters)
Featuring the voices of Danny Elfman, Chris Sarandon, Catherine O'Hara, William Hickey, and Ed Ivory Director: Henry Selick Producers: Tim Burton and Denise DiNovi Screenplay: Caroline Thompson based on an idea and characters by Tim Burton Music: Danny Elfman Released by Touchstone Pictures
When I was a child, one of the reasons I enjoyed the Christmas season so much was because of the annual arrival of those endlessly-repeated television specials: RUDOLPH THE RED-NOSED REINDEER, SANTA CLAUS IS COMING TO TOWN, THE YEAR WITHOUT A SANTA CLAUS. Tim Burton must remember those programs too, because in his own inimitable way, he has paid homage to them in this most twisted of holiday fairy tales, THE NIGHTMARE BEFORE CHRISTMAS.
The scene is Halloween Town where, not surprisingly, October 31 is the biggest night of the year. However, after arranging and carrying out his most devilish Halloween yet, Jack Skellington (voiced by Chris Sarandon when speaking, Danny Elfman when singing) is suffering the post-holiday blues. He craves something different in his life, something that can't be found in Halloween Town. Wandering out in a forest, he discovers gateways to different holidays, and finds his way to Christmas Town. There, he is captivated by the lights, the festivity, and the joy. He returns home to tell everyone that this year, Halloween Town is going to celebrate Christmas. To make things complete, he, Jack Skellington, will replace "Sandy Claws" on his yearly December 31 ride, delivering presents and spreading good cheer. Everyone is enthused by the idea except Sally (voiced by Catherine O'Hara), who has a premonition of doom if Jack goes through with his plans.
THE NIGHTMARE BEFORE CHRISTMAS is a visual splendor. Done on the cheap, this could have been a gimmicky, unsatisfying motion picture, but considering the obvious time and effort put into constructing the movie, it is an unqualified success. Everything moves smoothly and naturally, and the attention to detail is exquisite. We are given a clever cast of characters that look like something from Edward Gorey's sketchbook in a setting that oozes atmosphere. It is not difficult at all to become wrapped up in this movie.
The film is designed to be suitable for all but the youngest children, some of whom might be frightened by any of the bizarre inhabitants of Halloween Town (you know your childrens' natures and whether animated ghouls and goblins will terrify them or not). On its surface, the story has little more complexity than THE YEAR WITHOUT A SANTA CLAUS, so younger viewers will be able to enjoy the movie without feeling lost or bored. However, as is too rarely the case with family films, there is another level to this film. Much of the wryest humor is designed for adults.
Even those who aren't taken in by the charming-yet-simple story or the likable characters, will be enthralled by the world Tim Burton and director Henry Selick have created. It is, quite frankly, an amazing achievement, and one that we are not likely to see repeated for a long time.
THE NIGHTMARE BEFORE CHRISTMAS is HOW THE GRINCH STOLE CHRISTMAS thrown into reverse (although clearly the Dr. Seuss tale had a part in formulating some of the images of Christmas Town). While the Grinch made Christmas better by trying to destroy it, Jack Skellington ruins the holiday by trying to improve it. But don't worry - everything turns out all right in the end. This is, remember, a family film.
The biggest failing of THE NIGHTMARE BEFORE CHRISTMAS, and it shouldn't be overlooked, is the weakness of Danny Elfman's songs. With the exception of one or two, these are uniformly lifeless, and there are times when the movie might have been better without them. Something a little more energetic is called for. Elfman's score is more than adequate, but the songs are lacking.
Caroline Thompson, Tim Burton, and Danny Elfman have worked together before, and they appear have a good rapport when it comes to the unusual (the trio were all involved in EDWARD SCISSORHANDS). Each of them has invested a part of themselves in THE NIGHTMARE BEFORE CHRISTMAS, even as has Henry Selick, coordinator of the stop-motion animation.
THE NIGHTMARE BEFORE CHRISTMAS has something to offer just about everyone. For the kids, it's a fantasy celebrating two holidays. For the adults, it's an opportunity to experience some light entertainment while marvelling at how adept Hollywood has become at these techniques. There are songs (even if they aren't nearly as noteworthy as they should be), laughs, and a little romance. In short, THE NIGHTMARE BEFORE CHRISTMAS does what it intends to do: entertain.
- James Berardinelli<EMAIL_ADDRESS>.
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Showing a notification by snack bar without showing actions
Showing a notification by snack bar with a dismiss button


I came across independent music label Hypnotic Dirge Records’ account on Bandcamp via “Canadian prairie doom metal” band Alters of Grief.
Side note: there are endless sub-genres in metal.
The Saskatoon-based label says it supports “underground black metal, death-doom, experimental and more…” What was noteworthy to me was that you could not only by their entire 77 release digital back catalog for $25CAD, but that they offer subscription plans.
This may be common on Bandcamp for all I know. I’m buying from the site more often lately, but this is the first time I’ve noticed something like it.
I like the idea, though. It should help sustain the small label, increase exposure for their full roster of talent, and includes the subscriber in a way that gives them wide-open and ongoing access to music, new and old.
What would something like this look like for larger labels? Could they each have their own focused version of Spotify? Or would they just turn it into another BMG/Columbia House Music Club? Some, like Sony, have tried this, of course. I suspect it might work better for genre-specialized labels than for general, mass-media labels.
I prefer supporting artists as directly as I can, but for artists working a country away from me, supporting their indie label doesn’t seem like a bad way to go.


Shop Our
Baby & Kids Range
Item On sale
Item On sale
Item On sale
Categories
Party Supplies
Toys (TV Characters)
Kids Kitchen Store
Banners, Bunting & Garlands
Easter Decoration
Gift Wrapping Supplies
Kids Girls Accesorries
Girls Hair Accesorries
Kids Kitchen & Home Decoration
Kids Toys
Health & Beauty
Silicone Mobile Cover
Art and Crafts
Dog Play & Training Ball
Baby Products
Description
Shipping/Delivery
Return/Exchange
About Us


{% extends "base.html" %} {% block body %} Capture
GWaste app needs camera permission to be able to classify your waste.
Alternatively, if you already taken photo and want to upload a file instead, press the button below
Currently you blocked access to camera, or your browser is not supported.


Press n or j to go to the next uncovered block, b, p or k for the previous block.
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| cleanup.js | 19.19% | 19/99 | 43.75% | 14/32 | 100% | 2/2 | 19.19% | 19/99 | |
| docker-base.js | 81.4% | 70/86 | 42.42% | 14/33 | 100% | 9/9 | 82.35% | 70/85 | |
| docker-cli.js | 11.9% | 5/42 | 0% | 0/15 | 0% | 0/16 | 12.5% | 5/40 | |
| docker-prompts.js | 78.57% | 121/154 | 68.24% | 58/85 | 84.38% | 27/32 | 83.33% | 115/138 | |
| docker-utils.js | 33.33% | 15/45 | 34.78% | 8/23 | 33.33% | 2/6 | 33.33% | 14/42 | |
| generator-base-blueprint.js | 22.22% | 2/9 | 100% | 0/0 | 0% | 0/7 | 22.22% | 2/9 | |
| generator-base-docker.js | 100% | 49/49 | 50% | 1/2 | 100% | 8/8 | 100% | 49/49 | |
| generator-base-private.js | 56.54% | 255/451 | 49.82% | 140/281 | 67.03% | 61/91 | 55.81% | 245/439 | |
| generator-base.js | 47.88% | 395/825 | 50.97% | 210/412 | 54.23% | 77/142 | 47.43% | 387/816 | |
| generator-constants.js | 100% | 49/49 | 100% | 0/0 | 100% | 0/0 | 100% | 49/49 | |
| generator-transforms.js | 100% | 15/15 | 50% | 2/4 | 100% | 3/3 | 100% | 15/15 | |
| statistics.js | 76.19% | 64/84 | 68.52% | 37/54 | 56.52% | 13/23 | 80% | 64/80 | |
| utils.js | 80.52% | 124/154 | 66.67% | 50/75 | 81.25% | 26/32 | 80% | 120/150 |


Public Member Functions | |
| OutputFile () | |
| constructor | |
| OutputFile (const std::string &fpath) | |
| constructor | |
| virtual | ~OutputFile () |
| destructor | |
| size_t | write (const void *buffer, size_t size) throw (StreamException) |
| write to stream | |
| void | open (const std::string &fpath) |
| open | |
| void | close () |
| close | |
| bool | isValid () const |
| stream is valid or not |
| size_t OutputFile::write | ( | const void * | buffer, |
| size_t | size | ||
| ) | throw (StreamException) [virtual] |
write to stream
write data to stream
| buffer | buffer for data that you want to write |
| byte | byte you want to write |
Implements sinsy::IWritableStream.


WARNING
This webpage contains rapidly flashing images
Take me to safety
I understand and wish to continue


| Name | Location | Owner | Status | |
|---|---|---|---|---|
{{station.name}} |
{{station.bodyOfWater}} {{station.latitude}}, {{station.longitude}} |
{{station.teamLead.displayName}} {{station.schoolOrg.name}} |
{{station.status}} {{station.status}} |
Sorry, no Oyster Research Stations found for that search term or filter. Try widening your search.


{include file="../application/index/view/the1/base.html"/} {include file="the1/static/css/blog_read.css"}


New mac, mountain lion, and ruby.h not found
-
anonymous
Mountain Lion, installed command line tools. Have latest MacVim. Ruby is 1.8.7 and gcc is 4.2.1.
When I get to the ruby extconf.rb step, I get:
[bob:~LP_OLD_PWD/command-t] master(+912/-1) ± ruby extconf.rb (master) checking for ruby.h... no couldn't find ruby.h (required) [bob:~LP_OLD_PWD/command-t] master(+912/-1) 1 ±
Where would I have gotten ruby.h and where would it be located? Spotlight doesn't show the file.
-
Greg Hurrell
I think you'll need to install the Xcode tools for that; they are available on the Mac App store (for free).
Reply
This topic is now closed.


Welcome to infineon/python-optiga-trust
¶
optigatrust
python module is a ctypes based wrapper to work with the OPTIGA™ Trust security solutions.
Dependencies¶
Python 3.7+
CSR and X509 Handling - asn1crypto
For tests - oscrypto, cryptography
XML handling in export module jinja2
Keys wrap/unwrap operations cryptography
How does it work¶
This python module comes with a set of shared libraries, which are precompiled for different communication interfaces. The shared libraries are fully based on the official framework. This module doesn’t simply implement bindings for the library, but add many more things on top. See Documentation. In the end the module supports the following combinations
Interface/OS |
Windows |
Linux |
EvalKit |
Yes |
No |
PersoBoard |
Yes |
Yes |
Raw I2C |
No |
Yes |
Required Hardware¶
- Any of the following
OPTIGA™ Trust M1/M3/Charge EvalKit. See Provisioning mode for details.
OPTIGA™ Trust Personalisation Board, or any FTDI USB-HID/I2C Converter board
Raspberry Pi + Shield2Go RPi Adapter
OPTIGA™ Trust X/M/Charge sample or a Security Shield2Go
Note: If you use any of the embedded Linux as a Host, please don’t forget to enable i2c support in your kernel (RPi3: via raspi-config command), as well as add your user to the gpio group (RPi3: via sudo adduser pi gpio) RaspberryPi3 Connection Example.
Installation¶
$ pip install optigatrust
Testing¶
Tests are written using pytest and oscrypto and require these packages to be installed:
$ pip3 install pytest oscrypto
$ git clone --recurse-submodules https://github.com/Infineon/python-optiga-trust
...
$ cd python-optiga-trust
$ cd tests
$ pytest
To run only some tests, pass a regular expression as a parameter to tests.
$ pytest test_rand.py
- 1. OPTIGA™ Trust management
- 2. Object and Metadata management
- 3. Cryptography
- 3.1. True random number generation
- 3.2. Keypair generation (ECC, RSA)
- 3.3. Elliptic Curve Digital Signature Algorithm (ECDSA)
- 3.4. PKCS1 v1.5 Signature generation (RSA SSA)
- 3.5. Elliptic Curve Diffie-Hellman (ECDH)
- 3.6. Hash-based Message Authentication Code (HMAC)
- 3.7. Key Derivation (HKDF, TLS PRF)
- 3.8. API
- 4. CRS (Certificate Signing Request)
- 5. Export or Import Chip (Meta)Data
- 6. Porting to non-Raspberry Linux
- 7. Enable the provisioning mode on your Evaluation Kit
- 8. Copyrights and Licenses


Sorry, can not find what you are looking for.
If you feel this is a real problem,
contact IT
.
Go back to
FUM
?


Welcome to Street Lane Dental Centre (Leeds, UK). We are a committed team of dentists, hygiene/therapists, nurses and receptionists dedicated to giving you everything that a modern dental practice can offer. Our aim is to provide exceptional quality, individually tailored dental care to patients in a highly experienced, professional, relaxed and caring environment.
Our practice is a member of the British Dental Association’s Good Practice Scheme. This means that we are committed to a standard of good practice set by our professional association, BDA.
All our dentists, hygienists and nurses continually attend educational programmes to keep up to date with the constant changes in modern dentistry.
We take great pride in the quality of our dentistry and want to make your visit to us a pleasant experience. Our aim is to achieve good oral health for you and your family through preventative dentistry.
By taking the time to provide you with regular dental advice, we can help you understand how to take better care of your teeth yourself.
Please let us know if you require help with communication in any way. This may be related to the following:
In the interest of both patients and staff, we follow HTM0105 standards with respect to the sterilisation of our equipment.
We offer both NHS and Private dentistry for all, including children and have disabled access to the practice.
We always welcome your comments and feedback. This website provides you with an overview of our services, but please discuss with us any specific questions you may have.
We provide suggestion forms that you can fill in and post in our suggestion box. This is situated below the notice board in the waiting area.
Morning: 8:30am - 12:50pm
Afternoon: 2:00pm - 5:00pm
Morning: 8:30am - 12:50pm
Afternoon: 2:00pm - 4:00pm
Saturdays: By prior arrangement only
Sundays: Closed
We offer the full range of treatments including Cosmetic Dentistry, Whitening, Bridges, Crowns & Veneers, Preventative Care and all types of denture work. We particularly welcome anxious or phobic patients and take a sympathetic approach. We have the services of hygienists and oral health educators.
| EXAMINATIONS | |
| New Patient Exam | £85 |
| Routine Exam | £75 |
| Non-registered Emergency | £85 |
| Full Case Assessment | £110 |
| Children | £35 |
| FILLINGS | |
| Silver (Amalgam) Fillings | From £95 |
| White (Composite) Fillings | £120 |
| ROOT TREATMENT | |
| Incisor/Canine | £250 |
| Premolar | £300 |
| Molar | £350 |
| SURGICAL | |
| Extractions | £140 |
| CROWNS & VENEERS | |
| Crowns (varies with materials) | £510 - £585 |
| Porcelain Veneers | From £450 |
| Refix | £50 |
| BRIDGES | |
| Bridges | From £495 |
| DENTURES | |
| Acrylic - Full Upper | £550 |
| Acrylic - Partial (Simple) | £450 |
| Acrylic - Partial (Complex) | £570 |
| Metal-based | From £730 |
| HYGIENE | |
| 20-minute session | £48 |
| 30-minute session | £62 |
| 40-minute session | £79 |
| Air Polish | £35 |
| IMPLANTS | |
| Assessment | £125 |
| Implant | £2,200 (per implant) |
You can pay cash or by credit/debit card including Visa, MasterCard & Maestro. Unfortunately, we do not accept American Express. Denplan monthly payment schemes are available. If you are a member of Simply Health, or a private dental scheme, you may be able to claim reimbursements of dental fees.
You may qualify for free treatment under the NHS, so we will always endeavour to point this out to you if applicable.
If you have any questions, please speak to a member of our team for more information.
After looking for a dentist for a long time, which I could trust and felt comfortable with, I finally found Street Lane Dental Centre. As I am, to say the least, terrified and nervous. All the staff are friendly and professional, made me feel at ease and comfortable.
I have had many treatments there now and have recommended them to many friends and family.
I phoned up for an appointment last Wednesday having not been to see the dentist since 2010 and I got an appointment for the following morning. I was called for my check-up dead on my appointment time so no waiting.
The dentist was very friendly and made me feel at ease. Would highly recommend.
I have been attending this practice for many years now, commencing as an extremely nervous patient! However I cannot speak highly enough of all the team including reception, and their care and expertise is second to none. My needs have not been straight-forward but the team here have made it feel as if they were.
I highly recommend each and everyone of them and feel fortunate that I found them in the first place.


--- title: Alexa GUÉGUEN - Portfolio UX Designer - Alkemics Hosted Product Page permalink: alkemics-hpp.html --- {% include head.html title="Alexa GUÉGUEN - Portfolio UX Designer - Alkemics Hosted Product Page" %}
With the HPP (Hosted Product Page) all brands can send mandatory product data or any marketing content automatically on e-commerce websites, so retailers don’t break the European law ever again. And everybody is happy, including the end-consumer! 👏
Alkemics customers using the solution
My role in the project
I was commissioned by the CEO to answer a serious and recurring problem for AuchanDrive: the non-compliance of the product data. From research to launch, I led the project following the design sprint methodology.
Cabot Trail, NS, Canada 2017
Kickoff
As a sharing and managing data platform, it was key to quickly find a solution for all our users.
Here are the 3 challenges we were facing:
C = end-consumers ; R = retailers ; B = brands ; A= alkemics
Expert interviews
Retailers
Retrieve product data automatically in order to be compliant with the european regulation (INCO 1169).
Brands
Display marketing data like never before, and extend the brand experience on retailer e-commerce websites.
End-consumers
Access to the important information about the products and be confident with the purshase online.
Tweet
Explain the concept with few characters. Here is an example of what we could tweet.
Benchmarking
Screenshots of product pages of main French retailers websites in 2015.
Main pain points were the lack of data, the lisibility, the information architecture.
User journeys
My goal was to create a valuable experience for everyone, especially for our users: retailers and brands.
Here are the pain points we highlighted then solved.
1
I received a list of fines linked to non-compliant product displayed on my e-commerce website, and I’m not happy!
2
I upload this list in a spreadsheet with all the codebars and the brands associated to each product
3
I sort the products by brand name, to be able to contact the category manager, and command him to update the data
4
I threaten him/her to remove the brand from my assortment
1
I receive the retailer email and I’m surprised, stressed or angry because I already sent an excel file with all the data
2
I don’t understand why it doesn’t work, and why I sould do this twice on a platform called Alkemics…
3
I send again the data by email or I create an account on Alkemics with a lot of frustration and with no desire to stay
1
I send again the data by email or I create an account on Alkemics with a lot of frustration and with no desire to stay
2
I click on a product that seems interesting but I want to know more before purshasing
3
The product page is displayed but I only see few information but not the list of ingredients or how to prepare it…
4
I finally decide to close the product page, or even close the website because it doesn’t make me feel enough confident
Card sorting
I wrote important data on post-its. At the end, we grouped them into 11 themes.
Sketch, Zoning
The team took the time to sketch a lot of ideas.
Brainstorming, Sketching, Prototyping
The technical constraints give us a part of the solution.
To keep it simple, without having to put our hands in every partners systems, we decided to push data directly to the e-commerce website thanks to an iframe.
It allows to:
Results
Decrease the number of fines
Our first partner confirms us that the number of fines decreased quickly*
Increase the retention
Adding value on the Brands side help us retain users on Alkemics platform*
Delight end-consumers #AWARDS
Our work is awarded and many articles appeared in the specialized press
2 Awards won
Linéaires Award « Le qualiscope des drives » in 2015 & LSA Category Management Award in 2016
They talked bout us!
Many articles in the press
LesEchos.fr, LSA, Linéaires…
Links on Alkemics website
Retrospective
We did a great work in a minimum amount of time. The low priority project became an important part of the business. Thinking about what I could do better, I would say spending time to do some guerilla test but moslty thinking to the expected variations and minimize customization: each retailer wanted specific icons, colors and fonts to respect their own e-commerce website guidelines.
Next time, I will test ideas and obviously be more careful with the feature expectations like personnalization to anticipate the come up evolution.