xsl-list
[Top] [All Lists]

Re: [xsl] Source code formatting

2020-07-28 18:22:34
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(_at_)gmail(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 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(_at_)gmail(_dot_)com

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.
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>