Re: [xsl] Source code formatting

Subject: Re: [xsl] Source code formatting
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 28 Jul 2020 23:22:28 -0000
> The problem is that, due to attribute value normalization, carriage
returns are removed from attribute nodes during XML parsing.
> When using long XPath expressions (and this has become very common in
XSLT 3, especially with higher order functions),
> which are split in multiple lines, this results in huge single line
outputs which are impossible to read.

Just a hint (I actually do this... :)  ):

1. Keep your XPath expressions in separate *.xpath files.

2. Load the needed *.xpath files dynamically ( I do this with an
xpath-extension function currently written in XSLT, but this can be done in
XQuery, Java, or any suitable language).

3. Use or build your own XPath formatter. I created an XPath UDL
(User-Defined Language) file for Notepad++ and it works pretty well for me.
It looks like this, with only one one very long line :)

<NotepadPlus>
    <UserLang name="XPath" ext="xpath">
        <Settings>
            <Global caseIgnored="no" />
            <TreatAsSymbol comment="no" commentLine="no" />
            <Prefix words1="no" words2="yes" words3="no" words4="no" />
        </Settings>
        <KeywordLists>
            <Keywords name="Delimiters">&apos;&lt;0&apos;&gt;0</Keywords>
            <Keywords name="Folder+">{</Keywords>
            <Keywords name="Folder-">}</Keywords>
            <Keywords name="Operators">&apos; ! &quot; ( ) * , . / ; @ [ ]
? &lt;&lt; &lt; = &gt;&gt; &gt;</Keywords>
            <Keywords name="Comment">1(: 2:) 0</Keywords>
            <Keywords name="Keywords1">ancestor ancestor-or-self array as
attribute cast child comment descendant descendant-or-self element else eq
every except following following-sibling for function ge gt if instance
intersect item last le let lt map node parent position preceding
preceding-sibling processing-instruction return satisfies some subsequence
text then to</Keywords>
            <Keywords name="Keywords2">$</Keywords>
            <Keywords name="Keywords3">QName abs adjust-date-to-timezone
adjust-dateTime-to-timezone adjust-time-to-timezone analyze-string apply
available-environment-variables avg base-uri boolean ceiling
codepoint-equal codepoints-to-string collation-key collection compare
concat contains contains-token count current-date current-dateTime
current-time data dateTime day-from-date day-from-dateTime
days-from-duration deep-equal default-collation default-language
distinct-values doc doc-available document document-uri element-with-id
empty encode-for-uri ends-with error escape-html-uri escape-uri exactly-one
exists false filter fold-left fold-right for-each for-each-pair floor
format-date format-dateTime format-integer format-number format-time
function-arity function-lookup function-name function-available generate-id
has-children head hours-from-dateTime hours-from-duration hours-from-time
id idref implicit-timezone in-scope-prefixes index-of insert-before
inner-most iri-to-uri json-doc json-to-xml lang last load-xquery-module
local-name local-name-from-QName lower-case matches max min
minutes-from-dateTime minutes-from-duration minutes-from-time
month-from-date month-from-dateTime months-from-duration name namespace-uri
namespace-uri-for-prefix namespace-uri-from-QName nilled node-kind
node-name normalize-space normalize-unicode not number one-or-more
outermost parse-ietf-date parse-json parse-xml parse-xml-fragment path
position prefix-from-QName QName random-number-generator regex-group remove
replace resolve-QName resolve-uri reverse root round round-half-to-even
seconds-from-dateTime seconds-from-duration seconds-from-time serialize
sort starts-with static-base-uri string string-join string-length
string-pad string-to-codepoints subsequence substring substring-after
substring-before subtract-dateTimes-yielding-dayTimeDuration
subtract-dateTimes-yielding-yearMonthDuration sum system-property tail
timezone-from-date timezone-from-dateTime timezone-from-time tokenize trace
transform translate true type-available unordered unparsed-entity-public-id
unparsed-entity-uri unparsed-text unparsed-text-available
unparsed-text-lines upper-case uri-collection xml-to-json year-from-date
year-from-dateTime years-from-duration zero-or-one</Keywords>
        </KeywordLists>
        <Styles>
            <WordsStyle name="DEFAULT" styleID="11" fgColor="000000"
bgColor="FFFFFF" fontName="Courier New" fontStyle="0" fontSize="10" />
            <WordsStyle name="FOLDEROPEN" styleID="12" fgColor="000000"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="FOLDERCLOSE" styleID="13" fgColor="000000"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="KEYWORDS1" styleID="5" fgColor="800000"
bgColor="FFFFFF" fontName="" fontStyle="1" fontSize="10" />
            <WordsStyle name="KEYWORDS2" styleID="6" fgColor="0000A0"
bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="10" />
            <WordsStyle name="KEYWORDS3" styleID="8" fgColor="8000FF"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="COMMENT" styleID="1" fgColor="808080"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="COMMENT LINE" styleID="2" fgColor="000000"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="NUMBER" styleID="4" fgColor="000000"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="OPERATOR" styleID="10" fgColor="000000"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="DELIMITERS" styleID="14" fgColor="008000"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="DELIMINER2" styleID="15" fgColor="FF0000"
bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="DELIMINER3" styleID="16" fgColor="000000"
bgColor="FFFFFF" fontName="" fontStyle="0" />
        </Styles>
    </UserLang>
</NotepadPlus>

All of this works pretty well in practice. Here is a screenshot of the
Notepad++ formatting of special-folds.xpath, which itself loads dynamically
functions from two other *.xpath files: folds.xpath and operators.xpath:

https://github.com/dnovatchev/FXSL-XSLT2/blob/master/XPathFunctionLibraries.jpg



Hope this helps,

Dimitre

On Tue, Jul 28, 2020 at 2:17 PM Willem Van Lishout
willemvanlishout@xxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Hi list,
>
> Like many of you, I assume, I use a version control system when working on
> XSLT projects. I'm working together with multiple people, and we run the
> code through an XML formatter before checking it in to avoid formatting
> differences showing up in the diffs.
>
> The problem is that, due to attribute value normalization, carriage
> returns are removed from attribute nodes during XML parsing. When using
> long XPath expressions (and this has become very common in XSLT 3,
> especially with higher order functions), which are split in multiple lines,
> this results in huge single line outputs which are impossible to read.
>
> It seems any sort of XML processing will irreversibly transform the
> whitespace, therefore I have to choose between:
> - No formatting
> - Formatting using non-XML tools?
> - Finding a parser that bends the rules...
>
> Have any of you experienced the same problem and did you find a solution?
>
> Thanks.
>
> Willem Van Lishout
> willemvanlishout@xxxxxxxxx
>
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/782854> (by
> email <>)
>


-- 
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
To avoid situations in which you might make mistakes may be the
biggest mistake of all
------------------------------------
Quality means doing it right when no one is looking.
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play
-------------------------------------
To achieve the impossible dream, try going to sleep.
-------------------------------------
Facts do not cease to exist because they are ignored.
-------------------------------------
Typing monkeys will write all Shakespeare's works in 200yrs.Will they write
all patents, too? :)
-------------------------------------
Sanity is madness put to good use.
-------------------------------------
I finally figured out the only reason to be alive is to enjoy it.

Current Thread