From 6b91031ee26386c36eaccebcf15ecce9ade66e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20Gro=C3=9Fberndt?= Date: Thu, 9 Nov 2023 14:55:06 +0100 Subject: [PATCH] Switch to documentation tables based on xcore --- .github/workflows/ci.yml | 9 +- docs/asciidoc.css | 415 ------- docs/check-ojp-schemas.xsl | 92 -- docs/generate-tables.sh | 48 +- docs/generate_tables/custom-netex-perxsd.xml | 18 + docs/generate_tables/custom-ojp-perxsd.xml | 31 + docs/generate_tables/custom-ojp.xml | 136 +++ docs/generate_tables/custom-siri-perxsd.xml | 19 + docs/generate_tables/test-xco-sfilter.xq | 12 + docs/generate_tables/xco-check-input.xqm | 43 + docs/generate_tables/xco-comp-finder.xqm | 172 +++ docs/generate_tables/xco-comp-names.xqm | 155 +++ docs/generate_tables/xco-comp-reporter.xqm | 63 + docs/generate_tables/xco-constants.xqm | 4 + docs/generate_tables/xco-custom.xqm | 193 +++ docs/generate_tables/xco-dcache.xqm | 90 ++ docs/generate_tables/xco-debug.xqm | 81 ++ docs/generate_tables/xco-def.xqm | 131 ++ docs/generate_tables/xco-desc.xqm | 523 ++++++++ docs/generate_tables/xco-domain.xqm | 572 +++++++++ docs/generate_tables/xco-edesc-util.xqm | 545 +++++++++ docs/generate_tables/xco-edesc.xqm | 767 ++++++++++++ docs/generate_tables/xco-file-util.xqm | 222 ++++ docs/generate_tables/xco-html-util.xqm | 133 +++ docs/generate_tables/xco-html.xqm | 1056 +++++++++++++++++ docs/generate_tables/xco-link.xqm | 145 +++ docs/generate_tables/xco-namespace.xqm | 203 ++++ docs/generate_tables/xco-rdesc.xqm | 142 +++ docs/generate_tables/xco-report-util.xqm | 7 + docs/generate_tables/xco-reporter.xqm | 335 ++++++ .../xco-required-comp-descriptor.xqm | 105 ++ docs/generate_tables/xco-schema-resolver.xqm | 61 + docs/generate_tables/xco-sfilter.xqm | 303 +++++ .../generate_tables/xco-stype-description.xqm | 213 ++++ docs/generate_tables/xco-util.xqm | 338 ++++++ docs/generate_tables/xcore.xq | 161 +++ docs/generated/asciidoc.css | 451 +++---- docs/ojp-base.xsl | 60 - docs/ojp-prep-to-html-with-toc.xsl | 78 -- docs/ojp-prep-to-html.xsl | 518 -------- docs/ojp-to-prepdoc.xsl | 736 ------------ docs/schema-collection.xml | 25 - docs/theme.yml | 272 ----- docs/validate-schema-conventions.sh | 25 - 44 files changed, 7243 insertions(+), 2465 deletions(-) delete mode 100644 docs/asciidoc.css delete mode 100644 docs/check-ojp-schemas.xsl create mode 100644 docs/generate_tables/custom-netex-perxsd.xml create mode 100644 docs/generate_tables/custom-ojp-perxsd.xml create mode 100644 docs/generate_tables/custom-ojp.xml create mode 100644 docs/generate_tables/custom-siri-perxsd.xml create mode 100644 docs/generate_tables/test-xco-sfilter.xq create mode 100644 docs/generate_tables/xco-check-input.xqm create mode 100644 docs/generate_tables/xco-comp-finder.xqm create mode 100644 docs/generate_tables/xco-comp-names.xqm create mode 100644 docs/generate_tables/xco-comp-reporter.xqm create mode 100644 docs/generate_tables/xco-constants.xqm create mode 100644 docs/generate_tables/xco-custom.xqm create mode 100644 docs/generate_tables/xco-dcache.xqm create mode 100644 docs/generate_tables/xco-debug.xqm create mode 100644 docs/generate_tables/xco-def.xqm create mode 100644 docs/generate_tables/xco-desc.xqm create mode 100644 docs/generate_tables/xco-domain.xqm create mode 100644 docs/generate_tables/xco-edesc-util.xqm create mode 100644 docs/generate_tables/xco-edesc.xqm create mode 100644 docs/generate_tables/xco-file-util.xqm create mode 100644 docs/generate_tables/xco-html-util.xqm create mode 100644 docs/generate_tables/xco-html.xqm create mode 100644 docs/generate_tables/xco-link.xqm create mode 100644 docs/generate_tables/xco-namespace.xqm create mode 100644 docs/generate_tables/xco-rdesc.xqm create mode 100644 docs/generate_tables/xco-report-util.xqm create mode 100644 docs/generate_tables/xco-reporter.xqm create mode 100644 docs/generate_tables/xco-required-comp-descriptor.xqm create mode 100644 docs/generate_tables/xco-schema-resolver.xqm create mode 100644 docs/generate_tables/xco-sfilter.xqm create mode 100644 docs/generate_tables/xco-stype-description.xqm create mode 100644 docs/generate_tables/xco-util.xqm create mode 100644 docs/generate_tables/xcore.xq delete mode 100644 docs/ojp-base.xsl delete mode 100644 docs/ojp-prep-to-html-with-toc.xsl delete mode 100644 docs/ojp-prep-to-html.xsl delete mode 100644 docs/ojp-to-prepdoc.xsl delete mode 100644 docs/schema-collection.xml delete mode 100644 docs/theme.yml delete mode 100755 docs/validate-schema-conventions.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd087cafe..eff06498a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,10 +39,10 @@ jobs: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.ref }} - - name: Install xmllint and xsltproc + - name: Install java, xmllint and xsltproc run: | sudo apt-get update - sudo apt-get install libxml2-utils xsltproc + sudo apt-get install default-jre libxml2-utils xsltproc - name: Validate structure and lint XSD and XML files run: ./.github/scripts/validate-and-lint.sh @@ -50,9 +50,6 @@ jobs: - name: Validate OJP XML examples run: ./.github/scripts/validate-examples.sh - - name: Check schema structure for generation for documentation tables - run: ./docs/validate-schema-conventions.sh - - name: Generate documentation tables run: ./docs/generate-tables.sh @@ -75,7 +72,7 @@ jobs: target-folder: "${{steps.get-branch-name.outputs.BRANCH_NAME}}" - name: Remove generated documentation tables - run: rm -rf ./docs/generated/index.html + run: rm -rf ./docs/generated/documentation-tables - name: Commit changes uses: EndBug/add-and-commit@v9 # https://github.com/marketplace/actions/add-commit diff --git a/docs/asciidoc.css b/docs/asciidoc.css deleted file mode 100644 index ac9f43a90..000000000 --- a/docs/asciidoc.css +++ /dev/null @@ -1,415 +0,0 @@ -/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ -/* Remove comment around @import statement below when using as a custom stylesheet */ -/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ -article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} -audio,canvas,video{display:inline-block} -audio:not([controls]){display:none;height:0} -[hidden],template{display:none} -script{display:none!important} -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} -a{background:transparent} -a:focus{outline:thin dotted} -a:active,a:hover{outline:0} -h1{font-size:2em;margin:.67em 0} -abbr[title]{border-bottom:1px dotted} -b,strong{font-weight:bold} -dfn{font-style:italic} -hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} -mark{background:#ff0;color:#000} -code,kbd,pre,samp{font-family:monospace;font-size:1em} -pre{white-space:pre-wrap} -q{quotes:"\201C" "\201D" "\2018" "\2019"} -small{font-size:80%} -sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} -sup{top:-.5em} -sub{bottom:-.25em} -img{border:0} -svg:not(:root){overflow:hidden} -figure{margin:0} -fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} -legend{border:0;padding:0} -button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} -button,input{line-height:normal} -button,select{text-transform:none} -button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} -button[disabled],html input[disabled]{cursor:default} -input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} -input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box} -input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none} -button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} -textarea{overflow:auto;vertical-align:top} -table{border-collapse:collapse;border-spacing:0} -*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} -html,body{font-size:100%} -body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} -a:hover{cursor:pointer} -img,object,embed{max-width:100%;height:auto} -object,embed{height:100%} -img{-ms-interpolation-mode:bicubic} -.left{float:left!important} -.right{float:right!important} -.text-left{text-align:left!important} -.text-right{text-align:right!important} -.text-center{text-align:center!important} -.text-justify{text-align:justify!important} -.hide{display:none} -img,object,svg{display:inline-block;vertical-align:middle} -textarea{height:auto;min-height:50px} -select{width:100%} -.center{margin-left:auto;margin-right:auto} -.spread{width:100%} -p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6} -.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} -div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} -a{color:#2156a5;text-decoration:underline;line-height:inherit} -a:hover,a:focus{color:#1d4b8f} -a img{border:none} -p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} -p aside{font-size:.875em;line-height:1.35;font-style:italic} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} -h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} -h1{font-size:2.125em} -h2{font-size:1.6875em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} -h4,h5{font-size:1.125em} -h6{font-size:1em} -hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} -em,i{font-style:italic;line-height:inherit} -strong,b{font-weight:bold;line-height:inherit} -small{font-size:60%;line-height:inherit} -code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} -ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} -ul,ol{margin-left:1.5em} -ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} -ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} -ul.square{list-style-type:square} -ul.circle{list-style-type:circle} -ul.disc{list-style-type:disc} -ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} -dl dt{margin-bottom:.3125em;font-weight:bold} -dl dd{margin-bottom:1.25em} -abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} -abbr{text-transform:none} -blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} -blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} -blockquote cite:before{content:"\2014 \0020"} -blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} -blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} -@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} -h1{font-size:2.75em} -h2{font-size:2.3125em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} -h4{font-size:1.4375em}} -table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} -table thead,table tfoot{background:#f7f8f7;font-weight:bold} -table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} -table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} -table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} -table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} -h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} -.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table} -.clearfix:after,.float-group:after{clear:both} -*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} -*:not(pre)>code.nobreak{word-wrap:normal} -*:not(pre)>code.nowrap{white-space:nowrap} -pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} -em em{font-style:normal} -strong strong{font-weight:400} -.keyseq{color:rgba(51,51,51,.8)} -kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} -.keyseq kbd:first-child{margin-left:0} -.keyseq kbd:last-child{margin-right:0} -.menuseq,.menuref{color:#000} -.menuseq b:not(.caret),.menuref{font-weight:inherit} -.menuseq{word-spacing:-.02em} -.menuseq b.caret{font-size:1.25em;line-height:.8} -.menuseq i.caret{font-weight:bold;text-align:center;width:.45em} -b.button:before,b.button:after{position:relative;top:-1px;font-weight:400} -b.button:before{content:"[";padding:0 3px 0 2px} -b.button:after{content:"]";padding:0 2px 0 3px} -p a>code:hover{color:rgba(0,0,0,.9)} -#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} -#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table} -#header:after,#content:after,#footnotes:after,#footer:after{clear:both} -#content{margin-top:1.25em} -#content:before{content:none} -#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} -#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8} -#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px} -#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} -#header .details span:first-child{margin-left:-.125em} -#header .details span.email a{color:rgba(0,0,0,.85)} -#header .details br{display:none} -#header .details br+span:before{content:"\00a0\2013\00a0"} -#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} -#header .details br+span#revremark:before{content:"\00a0|\00a0"} -#header #revnumber{text-transform:capitalize} -#header #revnumber:after{content:"\00a0"} -#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} -#toc{border-bottom:1px solid #efefed;padding-bottom:.5em} -#toc>ul{margin-left:.125em} -#toc ul.sectlevel0>li>a{font-style:italic} -#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} -#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} -#toc li{line-height:1.3334;margin-top:.3334em} -#toc a{text-decoration:none} -#toc a:active{text-decoration:underline} -#toctitle{color:#7a2518;font-size:1.2em} -@media only screen and (min-width:768px){#toctitle{font-size:1.375em} -body.toc2{padding-left:15em;padding-right:0} -#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} -#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} -#toc.toc2>ul{font-size:.9em;margin-bottom:0} -#toc.toc2 ul ul{margin-left:0;padding-left:1em} -#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} -body.toc2.toc-right{padding-left:0;padding-right:15em} -body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}} -@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} -#toc.toc2{width:20em} -#toc.toc2 #toctitle{font-size:1.375em} -#toc.toc2>ul{font-size:.95em} -#toc.toc2 ul ul{padding-left:1.25em} -body.toc2.toc-right{padding-left:0;padding-right:20em}} -#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} -#content #toc>:first-child{margin-top:0} -#content #toc>:last-child{margin-bottom:0} -#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} -#footer-text{color:rgba(255,255,255,.8);line-height:1.44} -.sect1{padding-bottom:.625em} -@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}} -.sect1+.sect1{border-top:1px solid #efefed} -#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} -#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} -#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} -#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} -#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} -.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} -.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} -table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0} -.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)} -table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit} -.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} -.admonitionblock>table td.icon{text-align:center;width:80px} -.admonitionblock>table td.icon img{max-width:initial} -.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} -.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)} -.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} -.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} -.exampleblock>.content>:first-child{margin-top:0} -.exampleblock>.content>:last-child{margin-bottom:0} -.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} -.sidebarblock>:first-child{margin-top:0} -.sidebarblock>:last-child{margin-bottom:0} -.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} -.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} -.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} -.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} -.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em} -.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal} -@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} -@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} -.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} -.listingblock pre.highlightjs{padding:0} -.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} -.listingblock pre.prettyprint{border-width:0} -.listingblock>.content{position:relative} -.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} -.listingblock:hover code[data-lang]:before{display:block} -.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999} -.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"} -table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} -table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} -table.pyhltable td.code{padding-left:.75em;padding-right:0} -pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8} -pre.pygments .lineno{display:inline-block;margin-right:.25em} -table.pyhltable .linenodiv{background:none!important;padding-right:0!important} -.quoteblock{margin:0 1em 1.25em 1.5em;display:table} -.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} -.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} -.quoteblock blockquote{margin:0;padding:0;border:0} -.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} -.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} -.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right} -.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)} -.quoteblock .quoteblock blockquote{padding:0 0 0 .75em} -.quoteblock .quoteblock blockquote:before{display:none} -.verseblock{margin:0 1em 1.25em 1em} -.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} -.verseblock pre strong{font-weight:400} -.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} -.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} -.quoteblock .attribution br,.verseblock .attribution br{display:none} -.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} -.quoteblock.abstract{margin:0 0 1.25em 0;display:block} -.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0} -.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none} -table.tableblock{max-width:100%;border-collapse:separate} -table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0} -table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} -table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0} -table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0} -table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0} -table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0} -table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0} -table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0} -table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0} -table.frame-all{border-width:1px} -table.frame-sides{border-width:0 1px} -table.frame-topbot{border-width:1px 0} -th.halign-left,td.halign-left{text-align:left} -th.halign-right,td.halign-right{text-align:right} -th.halign-center,td.halign-center{text-align:center} -th.valign-top,td.valign-top{vertical-align:top} -th.valign-bottom,td.valign-bottom{vertical-align:bottom} -th.valign-middle,td.valign-middle{vertical-align:middle} -table thead th,table tfoot th{font-weight:bold} -tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} -tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} -p.tableblock>code:only-child{background:none;padding:0} -p.tableblock{font-size:1em} -td>div.verse{white-space:pre} -ol{margin-left:1.75em} -ul li ol{margin-left:1.5em} -dl dd{margin-left:1.125em} -dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} -ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} -ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} -ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} -ul.unstyled,ol.unstyled{margin-left:0} -ul.checklist{margin-left:.625em} -ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} -ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em} -ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden} -ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block} -ul.inline>li>*{display:block} -.unstyled dl dt{font-weight:400;font-style:normal} -ol.arabic{list-style-type:decimal} -ol.decimal{list-style-type:decimal-leading-zero} -ol.loweralpha{list-style-type:lower-alpha} -ol.upperalpha{list-style-type:upper-alpha} -ol.lowerroman{list-style-type:lower-roman} -ol.upperroman{list-style-type:upper-roman} -ol.lowergreek{list-style-type:lower-greek} -.hdlist>table,.colist>table{border:0;background:none} -.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} -td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} -td.hdlist1{font-weight:bold;padding-bottom:1.25em} -.literalblock+.colist,.listingblock+.colist{margin-top:-.5em} -.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top} -.colist>table tr>td:first-of-type img{max-width:initial} -.colist>table tr>td:last-of-type{padding:.25em 0} -.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} -.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0} -.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em} -.imageblock>.title{margin-bottom:0} -.imageblock.thumb,.imageblock.th{border-width:6px} -.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} -.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} -.image.left{margin-right:.625em} -.image.right{margin-left:.625em} -a.image{text-decoration:none;display:inline-block} -a.image object{pointer-events:none} -sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} -sup.footnote a,sup.footnoteref a{text-decoration:none} -sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} -#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} -#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0} -#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em} -#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none} -#footnotes .footnote:last-of-type{margin-bottom:0} -#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} -.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} -.gist .file-data>table td.line-data{width:99%} -div.unbreakable{page-break-inside:avoid} -.big{font-size:larger} -.small{font-size:smaller} -.underline{text-decoration:underline} -.overline{text-decoration:overline} -.line-through{text-decoration:line-through} -.aqua{color:#00bfbf} -.aqua-background{background-color:#00fafa} -.black{color:#000} -.black-background{background-color:#000} -.blue{color:#0000bf} -.blue-background{background-color:#0000fa} -.fuchsia{color:#bf00bf} -.fuchsia-background{background-color:#fa00fa} -.gray{color:#606060} -.gray-background{background-color:#7d7d7d} -.green{color:#006000} -.green-background{background-color:#007d00} -.lime{color:#00bf00} -.lime-background{background-color:#00fa00} -.maroon{color:#600000} -.maroon-background{background-color:#7d0000} -.navy{color:#000060} -.navy-background{background-color:#00007d} -.olive{color:#606000} -.olive-background{background-color:#7d7d00} -.purple{color:#600060} -.purple-background{background-color:#7d007d} -.red{color:#bf0000} -.red-background{background-color:#fa0000} -.silver{color:#909090} -.silver-background{background-color:#bcbcbc} -.teal{color:#006060} -.teal-background{background-color:#007d7d} -.white{color:#bfbfbf} -.white-background{background-color:#fafafa} -.yellow{color:#bfbf00} -.yellow-background{background-color:#fafa00} -span.icon>.fa{cursor:default} -a span.icon>.fa{cursor:inherit} -.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} -.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c} -.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} -.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900} -.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400} -.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000} -.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} -.conum[data-value] *{color:#fff!important} -.conum[data-value]+b{display:none} -.conum[data-value]:after{content:attr(data-value)} -pre .conum[data-value]{position:relative;top:-.125em} -b.conum *{color:inherit!important} -.conum:not([data-value]):empty{display:none} -dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} -h1,h2,p,td.content,span.alt{letter-spacing:-.01em} -p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} -p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} -p{margin-bottom:1.25rem} -.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} -.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} -.print-only{display:none!important} -@media print{@page{margin:1.25cm .75cm} -*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} -a{color:inherit!important;text-decoration:underline!important} -a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} -a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} -abbr[title]:after{content:" (" attr(title) ")"} -pre,blockquote,tr,img,object,svg{page-break-inside:avoid} -thead{display:table-header-group} -svg{max-width:100%} -p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} -h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} -#toc,.sidebarblock,.exampleblock>.content{background:none!important} -#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important} -.sect1{padding-bottom:0!important} -.sect1+.sect1{border:0!important} -#header>h1:first-child{margin-top:1.25rem} -body.book #header{text-align:center} -body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0} -body.book #header .details{border:0!important;display:block;padding:0!important} -body.book #header .details span:first-child{margin-left:0!important} -body.book #header .details br{display:block} -body.book #header .details br+span:before{content:none!important} -body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} -body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} -.listingblock code[data-lang]:before{display:block} -#footer{background:none!important;padding:0 .9375em} -#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em} -.hide-on-print{display:none!important} -.print-only{display:block!important} -.hide-for-print{display:none!important} -.show-for-print{display:inherit!important}} diff --git a/docs/check-ojp-schemas.xsl b/docs/check-ojp-schemas.xsl deleted file mode 100644 index 3139eaf1e..000000000 --- a/docs/check-ojp-schemas.xsl +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - Skipping... - - - - Checking... - - - - - - \033[1;33m[WARN] xs:choice with just one child! Context: \033[0m - - - \033[0;31m[ERROR] Documentation is not allowed on xs:choice! Context: \033[0m - - - - - - - - - - - - - \033[0;31m[ERROR] Group could not be resolved: - - - - - - - - \033[0;31m[ERROR] Unnamed complexTypes are not allowed inside complexTypes! Context: \033[0m - - - - - - - - - - - - \033[0;31m[ERROR] Documentation is not allowed on xs:sequence! Context: \033[0m - - - - - - - - - - - - - - - - \033[1;33m[WARN] Not implemented: \033[0m - - - - diff --git a/docs/generate-tables.sh b/docs/generate-tables.sh index 3e92f50e3..e5634ba21 100755 --- a/docs/generate-tables.sh +++ b/docs/generate-tables.sh @@ -1,34 +1,42 @@ #!/bin/bash -# Generate the documentation tables as docs/generated/OJP.html from the .xsd schema files +# Generate the documentation tables in docs/generated/ from the .xsd schema files # -# You need the binary `xsltproc` -# apt-get install xsltproc +# You need the binary `java` +# apt-get install default-jre # The -e flag causes the script to exit as soon as one command returns a non-zero exit code set -e +BASE_DIRECTORY=$(readlink -f "$(dirname "${0}")/..") +XSL_DIRECTORY="${BASE_DIRECTORY}/docs/generate_tables" +GENERATED_DIRECTORY="${BASE_DIRECTORY}/docs/generated" +BASEX_JAR="/tmp/basex.jar" + +if [ ! -e ${BASEX_JAR} ]; then + echo "Downloading BaseX ..." + wget --output-document=${BASEX_JAR} https://files.basex.org/releases/10.6/BaseX106.jar +fi + echo "Generating documentation tables ..." -base_dir="$(dirname "${0}")/.." -xsl_dir=$base_dir/docs -generated_dir="${base_dir}/docs/generated" +# prepare GENERATED_DIRECTORY +mkdir -p "${GENERATED_DIRECTORY}" +rm -f "${GENERATED_DIRECTORY}"/*.html -# prepare generated_dir -mkdir -p "${generated_dir}" -rm -f "${generated_dir}"/OJP-prep.xml "${generated_dir}"/*.adoc "${generated_dir}"/*.html -cp "${xsl_dir}"/asciidoc.css "${generated_dir}"/ +cd "${XSL_DIRECTORY}" -# create intermediate XML file for documentation -xsltproc --xinclude "${xsl_dir}"/ojp-to-prepdoc.xsl \ - "${xsl_dir}"/schema-collection.xml \ - >> "${generated_dir}"/OJP-prep.xml +java -cp ${BASEX_JAR} org.basex.BaseX \ + -b report=contab \ + -b dir="${BASE_DIRECTORY}" \ + -b odir="${GENERATED_DIRECTORY}" \ + -b custom=custom-ojp.xml \ + -b dnamesExcluded=".git .github" \ + xcore.xq -# generate stand-alone HTML file for documentation -xsltproc --xinclude "${xsl_dir}"/ojp-prep-to-html-with-toc.xsl \ - "${generated_dir}"/OJP-prep.xml \ - >> "${generated_dir}"/index.html +# Remove interim edesc files +rm -rf "${GENERATED_DIRECTORY}"/edesc -# remove intermediate XML file -rm -f "${generated_dir}"/OJP-prep.xml +# move to speaking name +mv "${GENERATED_DIRECTORY}"/contab "${GENERATED_DIRECTORY}"/documentation-tables echo -e '\033[0;32mFinished generating documentation tables\033[0m' diff --git a/docs/generate_tables/custom-netex-perxsd.xml b/docs/generate_tables/custom-netex-perxsd.xml new file mode 100644 index 000000000..a2594f94e --- /dev/null +++ b/docs/generate_tables/custom-netex-perxsd.xml @@ -0,0 +1,18 @@ + + + + Network Timetable EXchange + + + + + + + + + + + + + + diff --git a/docs/generate_tables/custom-ojp-perxsd.xml b/docs/generate_tables/custom-ojp-perxsd.xml new file mode 100644 index 000000000..d69192357 --- /dev/null +++ b/docs/generate_tables/custom-ojp-perxsd.xml @@ -0,0 +1,31 @@ + + + + Open API for distributed Journey Planning + + + + + + + + + + + + + + + diff --git a/docs/generate_tables/custom-ojp.xml b/docs/generate_tables/custom-ojp.xml new file mode 100644 index 000000000..103a4c96c --- /dev/null +++ b/docs/generate_tables/custom-ojp.xml @@ -0,0 +1,136 @@ + + + + Open API for distributed Journey + Planning + + + + + + + + + + + + + + + + + http://datex2.eu/schema/2_0RC1/2_0 + + + OJP - <strong>O</strong>pen API for distributed <strong>J</strong>ourney <strong>P</strong>lanning (datex2) + OJP Enumeration Dictionary - DATEX2 + datex2 + + + + + + http://wsdl.siri.org.uk + + + OJP - <strong>O</strong>pen API for distributed <strong>J</strong>ourney <strong>P</strong>lanning (wsdl) + OJP Enumeration Dictionary - WSDL + siri-wsdl + + + + + + http://www.ifopt.org.uk/acsb + + + OJP - <strong>O</strong>pen API for distributed <strong>J</strong>ourney <strong>P</strong>lanning (ACSB) + OJP Enumeration Dictionary - ACSB + acsb + + + + + + http://www.ifopt.org.uk/ifopt + + + OJP - <strong>O</strong>pen API for distributed <strong>J</strong>ourney <strong>P</strong>lanning (IFOPT) + OJP Enumeration Dictionary - IFOPT + ifopt + + + + + + http://www.opengis.net/gml/3.2 + + + OJP - <strong>O</strong>pen API for distributed <strong>J</strong>ourney <strong>P</strong>lanning (GML) + OJP Enumeration Dictionary - OJP + gml + + + + + + http://www.siri.org.uk/siri + + + OJP - <strong>O</strong>pen API for distributed <strong>J</strong>ourney <strong>P</strong>lanning (SIRI) + siri + + + + + + http://www.vdv.de/ojp + + + + OJP - <strong>O</strong>pen API for distributed <strong>J</strong>ourney <strong>P</strong>lanning + ojp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/generate_tables/custom-siri-perxsd.xml b/docs/generate_tables/custom-siri-perxsd.xml new file mode 100644 index 000000000..8711854c8 --- /dev/null +++ b/docs/generate_tables/custom-siri-perxsd.xml @@ -0,0 +1,19 @@ + + + + Server Interface for + Real-time Information (SIRI) + + + + + + + + + + + + + + diff --git a/docs/generate_tables/test-xco-sfilter.xq b/docs/generate_tables/test-xco-sfilter.xq new file mode 100644 index 000000000..2a16cf2ed --- /dev/null +++ b/docs/generate_tables/test-xco-sfilter.xq @@ -0,0 +1,12 @@ +import module namespace sf="http://www.parsqube.de/ns/xco/string-filter" +at 'xco-sfilter.xqm'; + +declare variable $s external := 'foo bar'; +declare variable $sfilter external := 'fo*'; + +let $csfilter := sf:compileStringFilter($sfilter) +let $result := sf:matchesStringFilter($s, $csfilter) +return + { + $csfilter + } \ No newline at end of file diff --git a/docs/generate_tables/xco-check-input.xqm b/docs/generate_tables/xco-check-input.xqm new file mode 100644 index 000000000..6592f1039 --- /dev/null +++ b/docs/generate_tables/xco-check-input.xqm @@ -0,0 +1,43 @@ +module namespace ci="http://www.parsqube.de/ns/xco/check-input"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +declare function ci:checkInput($report as xs:string?, + $dir as xs:string?, + $xsd as xs:string?, + $odir as xs:string?, + $ofile as xs:string?, + $domains as xs:string?, + $custom as xs:string?) + as empty-sequence() { + let $customElem := + if (not($custom)) then () + else + let $customPath := u:normalizeUri($custom, static-base-uri()) + return + if (not(doc-available($customPath))) then + error((), '*** Error - custom file not valid XML; path: '||$customPath) + else $customPath ! doc(.) + let $customDomains := $customElem/domains + return ( + if (not($ofile ! matches(., '[/\\]'))) then () else + error((), + 'Invalid $ofile value ("'||$ofile||'") - must be a file name, not a path. Aborted.') + , + if (not($ofile) or $odir) then () else + error((), + 'An $ofile value must be accompanied by an $odir value. Aborted.') + , + (: Report = contab: either custom domains, or odir, or ofile required :) + if ($report ne 'contab') then () else + if ($odir or $ofile or $domains or $customDomains) then () else + error((), + 'Report "contab" - either odir, or ofile, or domains, or custom domains '|| + 'must be specified. Aborted.') + + ) +}; diff --git a/docs/generate_tables/xco-comp-finder.xqm b/docs/generate_tables/xco-comp-finder.xqm new file mode 100644 index 000000000..e5159f23b --- /dev/null +++ b/docs/generate_tables/xco-comp-finder.xqm @@ -0,0 +1,172 @@ +module namespace cf="http://www.parsqube.de/ns/xco/comp-finder"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" +at "xco-util.xqm"; +import module namespace sf="http://www.parsqube.de/ns/xco/string-filter" +at "xco-sfilter.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Returns schema components (element declarations, attribute declarations, + : type definitions, group definitions, attribute group definitions) with a + : name matching string filters. + : + : @param enames a name filter for element declarations + : @param anames a name filter for attribute declarations + : @param tnames a name filter for type definitions + : @param gnames a name filter for group definitions + : @param hnames a name filter for attribute group definitions + : @param ens a name filter for the namespace of element declarations + : @param ans a name filter for the namespace of attribute declarations + : @param tns a name filter for the namespace of type definitions + : @param gns a name filter for the namespace of group definitions + : @param hns a name filter for the namespace of attribute group definitions + : @param global only top-level element declarations are considered + : @return schema components matching the component type specific name filter + :) +declare function cf:findComps($enames as xs:string?, + $anames as xs:string?, + $tnames as xs:string?, + $gnames as xs:string?, + $hnames as xs:string?, + $ens as xs:string?, + $ans as xs:string?, + $tns as xs:string?, + $gns as xs:string?, + $hns as xs:string?, + $global as xs:boolean?, + $schemas as element(xs:schema)+) + as element()* { + + let $enames := if (not($enames) and $ens) then '*' else $enames + let $anames := if (not($anames) and $ans) then '*' else $anames + let $tnames := if (not($tnames) and $tns) then '*' else $tnames + let $gnames := if (not($gnames) and $gns) then '*' else $gnames + let $hnames := if (not($hnames) and $hns) then '*' else $hnames + return if (empty(($enames, $anames, $tnames, $gnames, $hnames))) then $schemas/xs:element else + + let $enamesSF := $enames ! sf:compileStringFilter(.) + let $anamesSF := $anames ! sf:compileStringFilter(.) + let $tnamesSF := $tnames ! sf:compileStringFilter(.) + let $gnamesSF := $gnames ! sf:compileStringFilter(.) + let $hnamesSF := $hnames ! sf:compileStringFilter(.) + let $ensSF := $ens ! sf:compileStringFilter(.) + let $ansSF := $ans ! sf:compileStringFilter(.) + let $tnsSF := $tns ! sf:compileStringFilter(.) + let $gnsSF := $gns ! sf:compileStringFilter(.) + let $hnsSF := $hns ! sf:compileStringFilter(.) + return ( + if (not($enamesSF)) then () else + let $fschemas := $schemas[not($ensSF) or sf:matchesStringFilter(@targetNamespace, $ensSF)] + return + $fschemas/(if ($global) then xs:element else .//xs:element) + [sf:matchesStringFilter(@name, $enamesSF)], + if (not($anamesSF)) then () else + let $fschemas := $schemas[not($ansSF) or sf:matchesStringFilter(@targetNamespace, $ansSF)] + return + $fschemas/(if ($global) then xs:attribute else .//xs:attribute) + [sf:matchesStringFilter(@name, $anamesSF)], + if (not($tnamesSF)) then () else + let $fschemas := $schemas[not($tnsSF) or sf:matchesStringFilter(@targetNamespace, $tnsSF)] + return + $fschemas/(xs:simpleType, xs:complexType)[sf:matchesStringFilter(@name, $tnamesSF)], + if (not($gnamesSF)) then () else + let $fschemas := $schemas[not($gnsSF) or sf:matchesStringFilter(@targetNamespace, $gnsSF)] + return + $fschemas/xs:group[sf:matchesStringFilter(@name, $gnamesSF)], + if (not($hnamesSF)) then () else + let $fschemas := $schemas[not($hnsSF) or sf:matchesStringFilter(@targetNamespace, $hnsSF)] + return + $fschemas/xs:attributeGroup[sf:matchesStringFilter(@name, $hnamesSF)] + ) +}; + +(:~ + : Returns a group definition identified by QName. + :) +declare function cf:findGroup($qname as xs:QName, $schemas as element()*) + as element(xs:group)? { + let $comps := + $schemas[string(@targetNamespace) = namespace-uri-from-QName($qname)] + /xs:group[@name eq local-name-from-QName($qname)] + return + if (count($comps) le 1) then $comps else + let $baseUris := $comps/base-uri(.) + (: + let $_LOG := + trace($baseUris, '*** WARNING Multiple occurrence of group '||$qname||': ') + :) + return $comps[1] + +}; + +(:~ + : Returns an attribute group definition identified by QName. + :) +declare function cf:findAttributeGroup($qname as xs:QName, $schemas as element()*) + as element(xs:attributeGroup)? { + let $comps := + $schemas[string(@targetNamespace) = namespace-uri-from-QName($qname)] + /xs:attributeGroup[@name eq local-name-from-QName($qname)] + return $comps[1] +}; + +(:~ + : Returns a global element declaration identified by QName. + :) +declare function cf:findElement($qname as xs:QName, $schemas as element()*) + as element(xs:element)? { + let $comps := + $schemas[string(@targetNamespace) = namespace-uri-from-QName($qname)] + /xs:element[@name eq local-name-from-QName($qname)] + return + if (count($comps) le 1) then $comps else + let $baseUris := $comps/base-uri(.) + (: + let $_LOG := + trace($baseUris, '*** WARNING Multiple occurrence of element '||$qname||': ') + :) + return $comps[1] + +}; + +(:~ + : Returns a global attribute declaration identified by QName. + :) +declare function cf:findAttribute($qname as xs:QName, $schemas as element()*) + as element(xs:attribute)? { + let $comps := + $schemas[string(@targetNamespace) = namespace-uri-from-QName($qname)] + /xs:attribute[@name eq local-name-from-QName($qname)] + return $comps[1] +}; + +(:~ + : Returns a global type definition. + :) +declare function cf:findType($qname as xs:QName, $schemas as element()*) + as element()? { + let $comps := + $schemas[string(@targetNamespace) = namespace-uri-from-QName($qname)] + /(xs:complexType, xs:simpleType)[@name eq local-name-from-QName($qname)] + return + if (count($comps) le 1) then $comps else + (: + let $baseUris := $comps/base-uri(.) + let $_LOG := + trace($baseUris, '*** WARNING Multiple occurrence of type '||$qname||': ') + return + :) + $comps[1] +}; + +(:~ + : Returns a local type definition identified by type ID. + :) +declare function cf:findLocalType($typeID as xs:string, $schemas as element()*) + as element()? { + let $comps := $schemas//(xs:complexType, xs:simpleType)[@z:typeID eq $typeID] + let $_DEBUG := if (count($comps) le 1) then () else trace($comps/base-uri(.), '_COMP_BASE_URI: ') + return $comps[1] +}; diff --git a/docs/generate_tables/xco-comp-names.xqm b/docs/generate_tables/xco-comp-names.xqm new file mode 100644 index 000000000..934b5b4b1 --- /dev/null +++ b/docs/generate_tables/xco-comp-names.xqm @@ -0,0 +1,155 @@ +(: + : xco-comp-names - functions creating / evaluating a map of component names. + : Names are grouped by component kind, and each kind is represented by a + : map entry with a key corresponding to the kind. + : + : Keys: group, attributeGroup, element, attribute, type, localType. + : + : Names are qualified names, with the exception of local type names, + : which are strings obtained from the @z:typeID attribute. + :) +module namespace cn="http://www.parsqube.de/ns/xco/comp-names"; + +import module namespace cf="http://www.parsqube.de/ns/xco/comp-finder" +at "xco-comp-finder.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Maps a set of schema components to a map containing the component names. + : Map keys are the component kinds, map values the qualified component names + : or, in the case of local type components, the @z:typeID values. + : + : @param comps schema components + : @return a map of component names + :) +declare function cn:getCompNames($comps as element()*) + as map(xs:string, item()*) { + let $fnCompName := function($comp) {$comp/@name/QName(string(ancestor::xs:schema/@targetNamespace), .)} + let $groups := $comps/self::xs:group[@name]/$fnCompName(.) + let $attGroups := $comps/self::xs:attributeGroup[@name]/$fnCompName(.) + let $elems := $comps/self::xs:element/$fnCompName(.) + let $atts := $comps/self::xs:attribute/$fnCompName(.) + let $types := $comps/(self::xs:simpleType, self::xs:complexType)[@name]/$fnCompName(.) + let $localTypes := $comps/(self::xs:simpleType, self::xs:complexType)[not(@name)]/@z:typeID/string() + return + map:merge(( + map:entry('group', $groups)[exists($groups)], + map:entry('attributeGroup', $attGroups)[exists($attGroups)], + map:entry('element', $elems)[exists($elems)], + map:entry('attribute', $atts)[exists($atts)], + map:entry('type', $types)[exists($types)], + map:entry('localType', $localTypes)[exists($localTypes)] + )) +}; + +(:~ + : Merges two maps of component names into a single map. + : + : @param compNames1 a map of component names + : @param compNames2 another map of component names + : @return a map of component names + :) +declare function cn:mergeCompNames($compNames1 as map(xs:string, item()*)?, + $compNames2 as map(xs:string, item()*)?) + as map(xs:string, item()*) { + let $groups := ($compNames1?group, $compNames2?group) => distinct-values() + let $attributeGroups := ($compNames1?attributeGroup, $compNames2?attributeGroup) => distinct-values() + let $elements := ($compNames1?element, $compNames2?element) => distinct-values() + let $attributes := ($compNames1?attribute, $compNames2?attribute) => distinct-values() + let $types := ($compNames1?type, $compNames2?type) => distinct-values() + let $localTypes := ($compNames1?localType, $compNames2?localType) => distinct-values() + return + map:merge(( + map:entry('group', $groups)[exists($groups)], + map:entry('attributeGroup', $attributeGroups)[exists($attributeGroups)], + map:entry('element', $elements)[exists($elements)], + map:entry('attribute', $attributes)[exists($attributes)], + map:entry('type', $types)[exists($types)], + map:entry('localType', $localTypes)[exists($localTypes)] + )) +}; + +(:~ + : Returns a map of component names occurring in one map but not occurring in + : a second map. + : + : @param compNames1 a map of component names + : @param compNames2 another map of component names + : @return a map of component names + :) +declare function cn:compNamesExcept($compNames1 as map(xs:string, item()*), + $compNames2 as map(xs:string, item()*)) + as map(xs:string, item()*) { + let $groups := $compNames1?group[not(. = $compNames2?group)] + => distinct-values() + let $attributeGroups := $compNames1?attributeGroup[not(. = $compNames2?attributeGroup)] + => distinct-values() + let $elements := $compNames1?element[not(. = $compNames2?element)] + => distinct-values() + let $attributes := $compNames1?attribute[not(. = $compNames2?attribute)] + => distinct-values() + let $types := $compNames1?type[not(. = $compNames2?type)] + => distinct-values() + let $localTypes := $compNames1?localType[not(. = $compNames2?localType)] + => distinct-values() + return + map:merge(( + map:entry('group', $groups)[exists($groups)], + map:entry('attributeGroup', $attributeGroups)[exists($attributeGroups)], + map:entry('element', $elements)[exists($elements)], + map:entry('attribute', $attributes)[exists($attributes)], + map:entry('type', $types)[exists($types)], + map:entry('localType', $localTypes)[exists($localTypes)] + )) +}; + +(:~ + : Resolves qualified component names to the component elements. + : + : The names are provided as a map with component kinds as keys (group, + : attributeGroup, element, attribute, type, local type) and a sequence of + : names as values. + : + : The component elements are provided as a map with component kinds as keys + : and a sequence of component elements as values. + : + : @param compNames qualified component names arranged in a map + : @param schemas schema elements + : @param terminate if true, a fatal error is raised if a component cannot be + : found + : @return a map with component kinds as keys and sequences of component + : elements as values + :) +declare function cn:resolveCompNames($compNames as map(xs:string, item()*), + $schemas as element(xs:schema)*, + $terminate as xs:boolean?) + as map(xs:string, item()*) { + (: Function returning the components for the names of a particular component kind :) + let $fnFindComps := function($kind, $compNames, $schemas, $fnFind) { + let $names := $compNames($kind) + for $name in $names + let $comp := $fnFind($name, $schemas) + return + if (not($comp) and $terminate) then + error(QName((), 'COMPONENT_NOT_FOUND'), + 'Cannot resolve '||$kind||' - '|| + 'name: '||$name) + else $comp + } + return + + map:merge( + for $key in $compNames ! map:keys(.) + let $comps := + switch($key) + case 'group' return $fnFindComps($key, $compNames, $schemas, cf:findGroup#2) + case 'attributeGroup' return $fnFindComps($key, $compNames, $schemas, cf:findAttributeGroup#2) + case 'element' return $fnFindComps($key, $compNames, $schemas, cf:findElement#2) + case 'attribute' return $fnFindComps($key, $compNames, $schemas, cf:findAttribute#2) + case 'type' return $fnFindComps($key, $compNames, $schemas, cf:findType#2) + case 'localType' return $fnFindComps($key, $compNames, $schemas, cf:findLocalType#2) + default return error() + return map:entry($key, $comps) + ) +}; \ No newline at end of file diff --git a/docs/generate_tables/xco-comp-reporter.xqm b/docs/generate_tables/xco-comp-reporter.xqm new file mode 100644 index 000000000..8e8bda4f7 --- /dev/null +++ b/docs/generate_tables/xco-comp-reporter.xqm @@ -0,0 +1,63 @@ +module namespace cr="http://www.parsqube.de/ns/xco/comp-reporter"; + +import module namespace rp="http://www.parsqube.de/ns/xco/reporter" +at "xco-reporter.xqm"; + +import module namespace cf="http://www.parsqube.de/ns/xco/comp-finder" +at "xco-comp-finder.xqm"; + +import module namespace cd="http://www.parsqube.de/ns/xco/desc" +at "xco-desc.xqm"; + +import module namespace ed="http://www.parsqube.de/ns/xco/edesc" +at "xco-edesc.xqm"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" +at "xco-util.xqm"; + +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" +at "xco-namespace.xqm"; + +import module namespace co="http://www.parsqube.de/ns/xco/constants" +at "xco-constants.xqm"; + +import module namespace hl="http://www.parsqube.de/ns/xco/html" +at "xco-html.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +declare function cr:reportComps($reportType as xs:string?, + $enames as xs:string?, + $anames as xs:string?, + $tnames as xs:string?, + $gnames as xs:string?, + $hnames as xs:string?, + $ens as xs:string?, + $ans as xs:string?, + $tns as xs:string?, + $gns as xs:string?, + $hns as xs:string?, + $global as xs:boolean?, + $schemas as element(xs:schema)+, + $options as map(xs:string, item()*)) + as item()* { + let $nsmap := $options?nsmap + let $comps := cf:findComps( + $enames, $anames, $tnames, $gnames, $hnames, + $ens, $ans, $tns, $gns, $hns, + $global, $schemas ) + return + switch($reportType) + case 'def' return + rp:compDefReport($comps, $nsmap, $schemas, $options) + case 'edesc' return + rp:expandedCompDescsReport($comps, $nsmap, $schemas, $options) + case 'rdesc' return + rp:requiredCompDescsReport($comps, $nsmap, $schemas, $options) + case 'desc' return + rp:compDescsReport($comps, $nsmap, $schemas, $options) + case 'contab' return + rp:contabReport($comps, $nsmap, $schemas, $options) + default return error(QName((), 'UNKNOWN_REPORT_TYPE'), + 'Unknown report type: '||$reportType) +}; diff --git a/docs/generate_tables/xco-constants.xqm b/docs/generate_tables/xco-constants.xqm new file mode 100644 index 000000000..470494a6f --- /dev/null +++ b/docs/generate_tables/xco-constants.xqm @@ -0,0 +1,4 @@ +module namespace co="http://www.parsqube.de/ns/xco/constants"; + +(: Namespace URIs :) +declare variable $co:URI_XSD := "http://www.w3.org/2001/XMLSchema"; diff --git a/docs/generate_tables/xco-custom.xqm b/docs/generate_tables/xco-custom.xqm new file mode 100644 index 000000000..6faf77637 --- /dev/null +++ b/docs/generate_tables/xco-custom.xqm @@ -0,0 +1,193 @@ +(: + : Functions evaluating customization data. + :) +module namespace cu="http://www.parsqube.de/ns/xco/custom"; + +import module namespace dm="http://www.parsqube.de/ns/xco/domain" + at 'xco-domain.xqm'; +import module namespace u="http://www.parsqube.de/ns/xco/util" + at 'xco-util.xqm'; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Maps the customization document to an enhanced representation. + : + : @param path file path of the customization document + : @schemas the schemas to be evaluated + : @return enhanced customization document + :) +declare function cu:compileCustom($path as xs:string?, + $schemas as element(xs:schema)+, + $options as map(xs:string, item()*)) { + let $customElem := $path ! doc(.)/* + return + if ($customElem) then + $customElem/cu:compileCustomREC(., $schemas, $options) ! u:prettyNode(.) + else if (not($options?domains)) then () + else + { + dm:constructDomains((), $schemas, $options) + } +}; + +(:~ + : Recursive helper function of `compileCustom`. + :) +declare function cu:compileCustomREC($n as node(), + $schemas as element(xs:schema)+, + $options as map(xs:string, item()*)) + as node()* { + typeswitch($n) + case document-node() return document {$n/node() ! cu:compileCustomREC(., $schemas, $options)} + case element(domains) return () + case element(custom) return + element {node-name($n)} { + $n/@* ! cu:compileCustomREC(., $schemas, $options), + $n/node() ! cu:compileCustomREC(., $schemas, $options), + dm:constructDomains($n/domains, $schemas, $options) + } + case element() return + element {node-name($n)} { + $n/@* ! cu:compileCustomREC(., $schemas, $options), + $n/node() ! cu:compileCustomREC(., $schemas, $options) + } + default return $n +}; + +(:~ + : Returns the "title" of the XSD documentation as a whole. This title + : is displayed above the TOC providing links to the documentation + : resource. + : + : The title is returned as a sequence of nodes. + : + : @param reportType the report type + : @param custom customization element + : @param options options controlling the processing + : @return a sequence of nodes representing the title + :) +declare function cu:systemTitleNodes($reportType as xs:string?, + $custom as element()?, + $options as map(xs:string, item()*)) + as node()+ { + let $titleNodes := $custom/systemTitle/node() + return + if (empty($titleNodes)) then text {'XSD documentation - overview'} + else $titleNodes +}; + +(:~ + : Returns the "title" of the XSD documentation as a whole. This title + : is displayed above the TOC providing links to the documentation + : resource. + : + : The title is returned as a single string. + : + : @param reportType the report type + : @param custom customization element + : @param options options controlling the processing + : @return a string representing the title + :) +declare function cu:systemTitleString( + $reportType as xs:string?, + $custom as element()?, + $options as map(xs:string, item()*)) + as xs:string { + ($custom/systemTitle/string(.), 'XSD documentation - overview')[1] +}; + +(:~ + : Returns the "title" of an XSD, as used in the TOC of a report with a + : given report type. + :) +declare function cu:xsdTitle($schema as element(xs:schema), + $reportType as xs:string, + $domainId as xs:string?, + $custom as element()?) + as xs:string { + if (not($custom)) then 'Schema file: '||$schema/base-uri(.) ! file:name(.) else + + let $fnGetTitle := function($xsdTitlePref, $schema) { + switch($xsdTitlePref) + case 'singleSentenceAnno' return + let $anno := ($schema/xs:annotation/xs:documentation)[1] + where $anno + return replace($anno, '(.*?)\.\s.*', '$1') + case 'firstSentenceAnno' return + let $anno := $schema/xs:annotation/xs:documentation + where $anno + return replace($anno, '(.*?)\.\s.*', '$1') + case 'fileName' return + 'Schema file: '||$schema ! base-uri(.) ! file:name(.) + default return () + } + + let $reportTypeElem := cu:_getReportTypeElem($custom, $domainId, $reportType) + let $xsdTitle := $reportTypeElem/xsdTitle + let $pref1 := $xsdTitle/@pref1/$fnGetTitle(., $schema) + return if ($pref1) then $pref1 else + let $pref2 := $xsdTitle/@pref2/$fnGetTitle(., $schema) + return if ($pref2) then $pref2 else + let $pref3 := $xsdTitle/@pref3/$fnGetTitle(., $schema) + return if ($pref3) then $pref3 else + 'Schema file: '||$schema/base-uri(.) ! file:name(.) +}; + +(:~ + : Returns the (possibly) customized name of a component, as used in a report + : with a given report type. + : + : @param name the original QName, as a string + : @param componentKind the component kind (element, attribute, complexType, simpleType, group, attributeGroup) + : @param use main or sub, indicating if the component is the topic itself or referenced + : @param reportType the type of the report to be produced + : @param custom element defining customization + : @return the lexical name to be used in the report + :) +declare function cu:customComponentName($name as xs:string, + $componentKind as xs:string, + $use as xs:string, + $reportType as xs:string, + $domainId as xs:string?, + $custom as element()) + as xs:string { + let $reportTypeElem := cu:_getReportTypeElem($custom, $domainId, $reportType) + let $nameElem := $reportTypeElem/nameEdit + let $compNameElem := $nameElem/comp[@kind eq $componentKind][@use eq $use] + let $removePrefix := $compNameElem/@removePrefix + let $replace := $compNameElem/@replace + let $with := $compNameElem/@with + (: + let $_DEBUG := + if ($name ne 'ojp:AccessFeatureStatusEnumeration') then () + else trace(...) + :) + return + let $cuname := $name + let $cuname := if ($removePrefix = '*' + or (some $p in $removePrefix satisfies starts-with($name, $p||':'))) + then $cuname ! replace(., '^.+:', '') + else $cuname + let $cuname := if ($compNameElem/@replace) then $compNameElem/replace($cuname, @replace, @with) + else $cuname + return $cuname +}; + +(:~ + : Returns the relevant report type element defining the + : report type related cusgtomization. + :) +declare %private function cu:_getReportTypeElem( + $custom as element(custom), + $domainId as xs:string?, + $reportType as xs:string) + as element(reportType)? { + let $reportTypeElem := + if (not($domainId)) then () else + $custom/domains/domain[@id eq $domainId] + /processing/reportTypes/reportType[@name eq $reportType] + return if ($reportTypeElem) then $reportTypeElem else + $custom/reportTypes/reportType[@name eq $reportType] +}; + \ No newline at end of file diff --git a/docs/generate_tables/xco-dcache.xqm b/docs/generate_tables/xco-dcache.xqm new file mode 100644 index 000000000..c643759c9 --- /dev/null +++ b/docs/generate_tables/xco-dcache.xqm @@ -0,0 +1,90 @@ +(: + : xco-dcache - functions reading and updating the descriptor cache + :) +module namespace dc="http://www.parsqube.de/ns/xco/dcache"; + +import module namespace dg="http://www.parsqube.de/ns/xco/debug" + at "xco-debug.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; + +(: +import module namespace rd="http://www.parsqube.de/ns/xco/rdesc" + at "xco-rdesc.xqm"; +import module namespace cd="http://www.parsqube.de/ns/xco/desc" + at "xco-desc.xqm"; +import module namespace cn="http://www.parsqube.de/ns/xco/comp-names" + at "xco-comp-names.xqm"; +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; +import module namespace eu="http://www.parsqube.de/ns/xco/edesc-util" + at "xco-edesc-util.xqm"; +import module namespace sd="http://www.parsqube.de/ns/xco/simple-type-description" + at "xco-stype-description.xqm"; +:) + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Returns an expanded component descriptor retrieved from the dcache. + : + : @param a schema component + : @return the expanded component descriptor, or the empty sequence + :) +declare function dc:edescForComp($comp as element(), + $options as map(xs:string, item()*)) + as element()? { + let $edesc := $options?dcache?edesc?($comp/local-name())?(ns:componentQName($comp)) + (: + let $_DEBUG := if (not($edesc)) then () + else trace('_DCACHE: EDESC FOUND; KIND='||$comp/local-name()||', NAME='||$edesc/@z:name) + :) + return $edesc +}; + +(:~ + : Returns an expanded component descriptor retrieved from the dcache. + : + : @param a schema component + : @return the expanded component descriptor, or the empty sequence + :) +declare function dc:edescForQName($qname as xs:QName, + $kind as xs:string, + $options as map(xs:string, item()*)) + as element()? { + let $edesc := + if ($kind eq 'type') then + let $edescStype := $options?dcache?edesc?simpleType?($qname) + return + if ($edescStype) then $edescStype + else $options?dcache?edesc?complexType?($qname) + else $options?dcache?edesc?($kind)?($qname) + (: + let $_DEBUG := if (not($edesc)) then () + else trace('_DCACHE: EDESC FOUND; KIND='||$kind||', NAME='||$edesc/@z:name) + :) + return $edesc +}; + +declare function dc:storeEdesc($edesc as element(), + $options as map(xs:string, item()*)) + as map(xs:string, item()*) { + let $qname := $edesc/@z:name/resolve-QName(., ..) + let $kind := $edesc/local-name() + return if ($options?dcache?edesc?($kind)?($qname)) then $options else + + let $countEdescs0 := $options?dcache?edesc?($kind) ! map:keys(.) => count() + let $dcache := ($options?dcache, map{})[1] + let $edescCache := ($dcache?edesc, map{})[1] + let $kindCache := ($edescCache?($kind), map{})[1] + let $kindCacheUpd := map:put($kindCache, $qname, $edesc) + let $edescCacheUpd := map:put($edescCache, $kind, $kindCacheUpd) + let $dcacheUpd := map:put($dcache, 'edesc', $edescCacheUpd) + let $optionsNew := map:put($options, 'dcache', $dcacheUpd) + let $countEdescs := $optionsNew?dcache?edesc?($kind) ! map:keys(.) => count() + (: + let $_DEBUG := trace('_DCACHE: EDESC STORED; '|| + 'KIND='||$kind||', QNAME='||$qname||'; COUNT: '||$countEdescs0||'->'||$countEdescs) + :) + return $optionsNew +}; \ No newline at end of file diff --git a/docs/generate_tables/xco-debug.xqm b/docs/generate_tables/xco-debug.xqm new file mode 100644 index 000000000..d38c67a5e --- /dev/null +++ b/docs/generate_tables/xco-debug.xqm @@ -0,0 +1,81 @@ +(: + : xco-debug - functions providing debug functionality + :) +module namespace dg="http://www.parsqube.de/ns/xco/debug"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" +at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +declare variable $dg:DIR_DEBUG := '/projects/sbb/work'; + +(:~ + : Inserts into the options map a 'debug' entry, which is a map + : containing two keys: + : 'dir' - the output folder into which debug files are written + : 'filter' - a map associating debug ids with filter strings + : + : The 'debug' entry is evaluated by function db:WRITE_FILE. The + : entry controls where and if a file is written. + : + : Example: + : debugFilter: 5=PriceType, 7, 8=OrderElem + : debugDir: /projects/tmp + : + : 'debug' entry of options: + : debug: + : dir: /projects/tmp + : filter: + : 5: 'PriceType' + : 7: '*' + : 8: 'OrderElem + :) +declare function dg:SET_DEBUG_OPTIONS($debugDir as xs:string?, + $debugFilter as xs:string?, + $options as map(xs:string, item()*)) + as map(xs:string, item()*) { + if (not($debugFilter) and not($debugFilter)) then $options else + + let $filterItems := $debugFilter ! tokenize(., ',\s*') + let $filterMap := map:merge( + for $item in $filterItems + return + if (not(contains($item, '='))) then map:entry($item, '*') + else + let $id := replace($item, '\s*=.*', '') + let $cond := replace($item, '^.*?=\s*', '') + return map:entry($id, $cond)) + let $outputDir := ($debugDir, '.')[1] + let $debugMap := map{'dir': $outputDir, 'filter': $filterMap} + (: let $_DEBUG := trace($debugMap, '___DEBUG_MAP: ') :) + return map:put($options, 'debug', $debugMap) +}; + +declare function dg:WRITE_FILE($item as item()*, + $fname as xs:string, + $debugId as xs:string, + $debugCond as xs:string?, + $options as map(xs:string, item()*)) + as empty-sequence() { + if (empty($item) or empty($options?debug)) then () else + let $debugPass := $options?debug?filter($debugId) + return + if (not($debugPass = ('*', $debugCond))) then () else + + let $debugDir := ($options?debug?dir, '.')[1] + let $path := $debugDir||'/'||$fname + return + if ($item[1] instance of node()) then + file:write($path, $item ! u:prettyNode(.), map{'indent': 'yes'}) + else file:write($path, string-join($item, ' ')) +}; + +declare function dg:writeNode($fname as xs:string, + $node as node(), + $options as map(xs:string, item()*)) + as empty-sequence() { + let $path := $dg:DIR_DEBUG||'/'||$fname + return + file:write($path, $node, $options) +}; diff --git a/docs/generate_tables/xco-def.xqm b/docs/generate_tables/xco-def.xqm new file mode 100644 index 000000000..dc996a370 --- /dev/null +++ b/docs/generate_tables/xco-def.xqm @@ -0,0 +1,131 @@ +(: + + : xco-def.xpm - functions supporting def reports. + :) +module namespace df="http://www.parsqube.de/ns/xco/def"; + +import module namespace dm="http://www.parsqube.de/ns/xco/domain" + at "xco-domain.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Writes for each domain a def report file. + : + : @param comps schema components + : @param nsmap a map of namespace bindings + : @param schemas the schemas to be evaluated + : @param options options controlling the processing + : @return empty sequence + :) +declare function df:writeCompDefDomainReports( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as item()? { + let $domains := $options?domains/domain + return if (not($domains)) then () else + + let $domainXsdComponentMaps := + dm:getDomainXsdComponentMaps($comps, $domains, $schemas, $options) + for $domain in $domains + let $domainXsdComponentMap := $domainXsdComponentMaps[?domain is $domain] + let $xsdReports := + for $filePath in $domainXsdComponentMap?xsds ! map:keys(.) + let $comps := $domainXsdComponentMap?xsds($filePath) + where $comps + let $compsGrouped := + for $comp in $comps + let $kind := $comp/local-name(.) + group by $kind + order by $kind + return + { + $comp + } + order by $filePath + return + { + $compsGrouped + } + let $countComps := count($xsdReports/z:components/*) + where $countComps + let $domainReportRaw := + { + for $xsdReport in $xsdReports[@countComps > 0] + let $filePath := $xsdReport/@filePath + order by $filePath + return + { + $xsdReport/@countComps, + $xsdReport/* + } + }/ns:addNamespaceContext(., $nsmap, ())/u:prettyNode(.) + + let $domainReport := + if ($options?skipAnno) then $domainReportRaw/u:removeAnno(.)/u:prettyNode(.) + else $domainReportRaw/u:prettyNode(.) + + let $reportFilePath := dm:getReportPath('def', $domain, $options) + let $_LOG := trace('*** Write def report: '||$reportFilePath) + let $_WRITE := u:writeXmlDoc($reportFilePath, $domainReport) + return () +}; + +(:~ + : Writes a def report file. + : + : @param comps schema components + : @param nsmap a map of namespace bindings + : @param schemas the schemas to be evaluated + : @param options options controlling the processing + : @return empty sequence + :) +declare function df:writeCompDefReport( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as item()? { + let $ofile := $options?ofile + let $reports := + for $comp in $comps + let $filePath := $comp/base-uri(.) ! u:normalizeUri(., ()) + group by $filePath + order by $filePath + let $compsGrouped := + for $comp2 in $comp + let $kind := $comp2/local-name(.) + group by $kind + order by $kind + return + { + $comp2 + } + return + { + $compsGrouped + } + let $creports := + if ($options?skipAnno) then $reports/u:removeAnno(.)/u:prettyNode(.) + else $reports/u:prettyNode(.) + let $report := + { + $creports + }/ns:addNamespaceContext(., $nsmap, ()) + return + (: Either write file or return the report :) + if ($ofile) then ( + file:write($ofile, $report, map{'indent': 'yes'}), + trace((), 'Report file written: '||$ofile)) + else $report +}; diff --git a/docs/generate_tables/xco-desc.xqm b/docs/generate_tables/xco-desc.xqm new file mode 100644 index 000000000..3785deb48 --- /dev/null +++ b/docs/generate_tables/xco-desc.xqm @@ -0,0 +1,523 @@ +(: + : xco-comp-descriptor - functions creating component descriptors + :) +module namespace cd="http://www.parsqube.de/ns/xco/desc"; + +import module namespace cf="http://www.parsqube.de/ns/xco/comp-finder" +at "xco-comp-finder.xqm"; + +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" +at "xco-namespace.xqm"; + +import module namespace cn="http://www.parsqube.de/ns/xco/comp-names" +at "xco-comp-names.xqm"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" +at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Describe me + : + : @param comps schema components + : @return component descriptors + :) +declare function cd:getCompDescs($comps as element()*, + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)) + as element()* { + for $comp in $comps[@name or @z:typeID] + let $desc := + typeswitch($comp) + case element(xs:group) return cd:getGroupCompDescs($comp, $nsmap, $options) + case element(xs:attributeGroup) return cd:getAttributeGroupCompDescs($comp, $nsmap, $options) + case element(xs:element) return cd:getElementCompDescs($comp, $nsmap, $options) + case element(xs:attribute) return cd:getAttributeCompDescs($comp, $nsmap, $options) + case element(xs:simpleType) return cd:getSimpleTypeCompDescs($comp, $nsmap, $options) + case element(xs:complexType) return cd:getComplexTypeCompDescs($comp, $nsmap, $options) + default return error() + return $desc/ns:addNamespaceContext(., $nsmap, map{'baseUri': $comp/base-uri(.)}) +}; + +(:~ + : Maps group definitions to component descriptors. + : + : @param comps group definitions + : @param nsmap a map describing standardized namespace bindings + : @return group component descriptors + :) +declare function cd:getGroupCompDescs($comps as element(xs:group)*, + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + $comps/cd:getGroupCompDescsREC(., $nsmap, $options) +}; + +(:~ + : Recursive helper function of `getGroupCompDescs`. + :) +declare function cd:getGroupCompDescsREC($n as node(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as node()* { + typeswitch($n) + case element(xs:all) | element(xs:choice) | element(xs:sequence) return + $n/cd:copyElem(., cd:getGroupCompDescsREC#3, $nsmap, $options) + case element(xs:annotation) | element(xs:appinfo) | element(xs:documentation) return + $n/cd:copyElem(., cd:getGroupCompDescsREC#3, $nsmap, $options) + case element(xs:element) return + $n/cd:copyElementElem(., cd:getGroupCompDescsREC#3, $nsmap, $options) + case element(xs:group) return + $n/cd:copyElem(., cd:getGroupCompDescsREC#3, $nsmap, $options) + case element() return + $n/cd:copyOtherElem(., cd:getGroupCompDescsREC#3, $nsmap, $options) + + (: attributes :) + case attribute(base) return $n/cd:writeTypeAtt(., $nsmap, $options) + case attribute(default) return $n/cd:copyAtt(., $options) + case attribute(maxOccurs) return $n/cd:copyAtt(., $options) + case attribute(minOccurs) return $n/cd:copyAtt(., $options) + case attribute(name) return $n/cd:copyNameAtt(., $nsmap, $options) + case attribute(ref) return $n/cd:copyQNameAtt(., $nsmap, $options) + case attribute(type) return $n/cd:writeTypeAtt(., $nsmap, $options) + case attribute(z:typeID) return $n/cd:writeTypeIdAtt(., $nsmap, $options) + case attribute() return $n/cd:copyOtherAtt(., $options) + case text() | comment() return $n + default return $n +}; + +(:~ + : Maps attribute group definitions to component descriptors. + : + : @param comps attribute group definitions) + : @param nsmap a map describing standardized namespace bindings + : @return group component descriptors + :) +declare function cd:getAttributeGroupCompDescs($comps as element(xs:attributeGroup)*, + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + $comps/cd:getAttributeGroupCompDescsREC(., $nsmap, $options) +}; + +(:~ + : Recursive helper function of `getAttributeGroupCompDescs`. + :) +declare function cd:getAttributeGroupCompDescsREC($n as node(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as node()* { + typeswitch($n) + case element(xs:annotation) | element(xs:appinfo) | element(xs:documentation) return + $n/cd:copyElem(., cd:getAttributeGroupCompDescsREC#3, $nsmap, $options) + case element(xs:attribute) return + $n/cd:copyAttributeElem(., cd:getAttributeGroupCompDescsREC#3, $nsmap, $options) + case element(xs:attributeGroup) return + $n/cd:copyElem(., cd:getAttributeGroupCompDescsREC#3, $nsmap, $options) + case element() return + $n/cd:copyOtherElem(., cd:getAttributeGroupCompDescsREC#3, $nsmap, $options) + + (: attributes :) + case attribute(default) return $n/cd:copyAtt(., $options) + case attribute(name) return $n/cd:copyNameAtt(., $nsmap, $options) + case attribute(ref) return $n/cd:copyQNameAtt(., $nsmap, $options) + case attribute(type) return $n/cd:writeTypeAtt(., $nsmap, $options) + case attribute(use) return $n/cd:copyAtt(., $options) + case attribute(z:typeID) return $n/cd:writeTypeIdAtt(., $nsmap, $options) + case attribute() return $n/cd:copyOtherAtt(., $options) + case text() | comment() return $n + default return $n +}; + +(:~ + : Maps element declarations to component descriptors. + : + : @param comps element declarations + : @param nsmap a map describing standardized namespace bindings + : @return group component descriptors + :) +declare function cd:getElementCompDescs($comps as element(xs:element)*, + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + $comps/cd:getElementCompDescsREC(., $nsmap, $options) +}; + +(:~ + : Recursive helper function of `getElementCompDescs`. + :) +declare function cd:getElementCompDescsREC($n as node(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as node()* { + typeswitch($n) + case element(xs:annotation) | element(xs:appinfo) | element(xs:documentation) return + $n/cd:copyElem(., cd:getElementCompDescsREC#3, $nsmap, $options) + case element(xs:element) return + $n/cd:copyElementElem(., cd:getElementCompDescsREC#3, $nsmap, $options) + case element(xs:field) | + element(xs:key) | + element(xs:keyref) | + element(xs:selector) | + element(xs:unique) return $n/cd:copyElem(., cd:getElementCompDescsREC#3, $nsmap, $options) + case element() return + $n/cd:copyOtherElem(., cd:getAttributeGroupCompDescsREC#3, $nsmap, $options) + + (: attributes :) + case attribute(abstract) return $n/cd:copyAtt(., $options) + case attribute(default) return $n/cd:copyAtt(., $options) + case attribute(fixed) return $n/cd:copyAtt(., $options) + case attribute(id) return $n/cd:copyAtt(., $options) + case attribute(minOccurs) | + attribute(maxOccurs) return $n/cd:copyAtt(., $options) + case attribute(name) return $n/cd:copyNameAtt(., $nsmap, $options) + case attribute(ref) return $n/cd:copyQNameAtt(., $nsmap, $options) + case attribute(refer) return $n/cd:copyQNameAtt(., $nsmap, $options) + case attribute(substitutionGroup) return $n/cd:copyQNameAtt(., $nsmap, $options) + case attribute(type) return $n/cd:writeTypeAtt(., $nsmap, $options) + case attribute(xpath) return $n/cd:copyAtt(., $options) + case attribute(z:typeID) return $n/cd:writeTypeIdAtt(., $nsmap, $options) + case attribute() return $n/cd:copyOtherAtt(., $options) + case text() | comment() return $n + default return $n +}; + +(:~ + : Maps attribute declarations to component descriptors. + : + : @param comps attribute declarations + : @param nsmap a map describing standardized namespace bindings + : @return group component descriptors + :) +declare function cd:getAttributeCompDescs($comps as element(xs:attribute)*, + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + $comps/cd:getAttributeCompDescsREC(., $nsmap, $options) +}; + +(:~ + : Recursive helper function of `getAttributeCompDescs`. + :) +declare function cd:getAttributeCompDescsREC($n as node(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as node()* { + typeswitch($n) + case element(xs:annotation) | element(xs:appinfo) | element(xs:documentation) return + $n/cd:copyElem(., cd:getAttributeCompDescsREC#3, $nsmap, $options) + case element(xs:attribute) return + $n/cd:copyAttributeElem(., cd:getAttributeCompDescsREC#3, $nsmap, $options) + case element() return + $n/cd:copyOtherElem(., cd:getAttributeCompDescsREC#3, $nsmap, $options) + + (: attributes :) + case attribute(default) return $n/cd:copyAtt(., $options) + case attribute(fixed) return $n/cd:copyAtt(., $options) + case attribute(name) return $n/cd:copyNameAtt(., $nsmap, $options) + case attribute(ref) return $n/cd:copyQNameAtt(., $nsmap, $options) + case attribute(type) return $n/cd:writeTypeAtt(., $nsmap, $options) + case attribute(use) return $n/cd:copyAtt(., $options) + case attribute(z:typeID) return $n/cd:writeTypeIdAtt(., $nsmap, $options) + case attribute() return $n/cd:copyOtherAtt(., $options) + case text() | comment() return $n + default return $n +}; + +(:~ + : Maps schema complex type definitions to component descriptors. + : + : @param comps complex type definitions + : @param nsmap a map describing standardized namespace bindings + : @return group component descriptors + :) +declare function cd:getComplexTypeCompDescs( + $comps as element(xs:complexType)*, + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element(z:complexType) { + $comps/cd:getComplexTypeCompDescsREC(., $nsmap, $options) +}; + +(:~ + : Recursive helper function of function `getComplexTypeCompDescs`. + :) +declare function cd:getComplexTypeCompDescsREC( + $n as node(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as node()* { + typeswitch($n) + case element(xs:all) | element(xs:choice) | element(xs:sequence) return + $n/cd:copyElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:annotation) | element(xs:appinfo) | element(xs:documentation) return + $n/cd:copyElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:attribute) return + $n/cd:copyAttributeElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:attributeGroup) return + $n/cd:copyElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:complexContent) | element(xs:simpleContent) return + $n/cd:copyElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:complexType) return + $n/cd:copyTypeElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:element) return + $n/cd:copyElementElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:extension) | element(xs:restriction) return + $n/cd:copyElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:group) return + $n/cd:copyElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element(xs:any) return + $n/cd:copyElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + case element() return + $n/cd:copyOtherElem(., cd:getComplexTypeCompDescsREC#3, $nsmap, $options) + + (: attributes :) + case attribute(abstract) return $n/cd:copyAtt(., $options) + case attribute(base) return $n/cd:writeTypeAtt(., $nsmap, $options) + case attribute(default) return $n/cd:copyAtt(., $options) + case attribute(fixed) return $n/cd:copyAtt(., $options) + case attribute(maxOccurs) return $n/cd:copyAtt(., $options) + case attribute(minOccurs) return $n/cd:copyAtt(., $options) + case attribute(name) return $n/cd:copyNameAtt(., $nsmap, $options) + case attribute(namespace) return $n/cd:copyAtt(., $options) + case attribute(processContents) return $n/cd:copyAtt(., $options) + case attribute(ref) return $n/cd:copyQNameAtt(., $nsmap, $options) + case attribute(type) return $n/cd:writeTypeAtt(., $nsmap, $options) + case attribute(use) return $n/cd:copyAtt(., $options) + case attribute(xml:lang) return $n/cd:copyAtt(., $options) + case attribute(z:typeID) return $n/cd:writeTypeIdAtt(., $nsmap, $options) + case attribute() return $n/cd:copyOtherAtt(., $options) + case text() | comment() return $n + default return $n +}; + +(:~ + : Maps simple type definitions to component descriptors. + : + : @param simple type definitions + : @param nsmap a map describing standardized namespace bindings + : @return group component descriptors + :) +declare function cd:getSimpleTypeCompDescs($comps as element(xs:simpleType)*, + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + $comps/cd:getSimpleTypeCompDescsREC(., $nsmap, $options) +}; + +(:~ + : Recursive helper function of function `getSimpleTypeCompDescs`. + :) +declare function cd:getSimpleTypeCompDescsREC( + $n as node(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as node()* { + typeswitch($n) + case element(xs:annotation) | element(xs:appinfo) | element(xs:documentation) return + $n/cd:copyElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element(xs:enumeration) | element(xs:pattern) return + $n/cd:copyElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element(xs:extension) | element(xs:restriction) return + $n/cd:copyElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element(xs:list) | element(xs:union) return + $n/cd:copyElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element(xs:maxExclusive) | element(xs:maxInclusive) return + $n/cd:copyElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element(xs:minExclusive) | element(xs:minInclusive) return + $n/cd:copyElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element(xs:maxLength) | element(xs:minLength) return + $n/cd:copyElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element(xs:simpleType) return + $n/cd:copyTypeElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element(xs:any) return + $n/cd:copyElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + case element() return + $n/cd:copyOtherElem(., cd:getSimpleTypeCompDescsREC#3, $nsmap, $options) + + (: attributes :) + case attribute(base) return cd:writeTypeAtt($n, $nsmap, $options) + case attribute(final) return $n/cd:copyAtt(., $options) + case attribute(fixed) return $n/cd:copyAtt(., $options) + case attribute(itemType) return $n/cd:copyQNameAtt(., $nsmap, $options) + case attribute(memberTypes) return $n/cd:copyQNamesAtt(., $nsmap, $options) + case attribute(name) return cd:copyNameAtt($n, $nsmap, $options) + case attribute(processContents) return $n/cd:copyAtt(., $options) + case attribute(value) return $n/cd:copyAtt(., $options) + case attribute(xml:lang) return $n/cd:copyAtt(., $options) + case attribute(z:typeID) return $n/cd:writeTypeIdAtt(., $nsmap, $options) + case attribute() return $n/cd:copyOtherAtt(., $options) + case text() | comment() return $n + default return $n +}; + +(: + : U t i l i t i e s + : ================= + :) + + declare function cd:copyElem($elem as element(), + $fnRec as function(*), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + element {'z:'||local-name($elem)} { + $elem/@* ! $fnRec(., $nsmap, $options), + $elem/(self::xs:group[@ref], self::xs:sequence, self::xs:choice)/cd:writeOccAtt(.), + $elem/node() ! $fnRec(., $nsmap, $options) + } +}; + +declare function cd:copyElementElem($elem as element(), + $fnRec as function(*), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element(z:element) { + $elem/element {'z:'||local-name(.)} { + @* ! $fnRec(., $nsmap, $options), + $elem[not(parent::xs:schema)]/cd:writeOccAtt(.), + (xs:simpleType, xs:complexType)/@z:typeID ! $fnRec(., $nsmap, $options), + (node() except (xs:simpleType, xs:complexType)) ! $fnRec(., $nsmap, $options) + } +}; + +declare function cd:copyAttributeElem($elem as element(), + $fnRec as function(*), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element(z:attribute) { + $elem/element {'z:'||local-name(.)} { + @* ! $fnRec(., $nsmap, $options), + $elem[not(parent::xs:schema)]/cd:writeOccAtt(.), + xs:simpleType/@z:typeID ! $fnRec(., $nsmap, $options), + (node() except xs:simpleType) ! $fnRec(., $nsmap, $options) + } +}; + +declare function cd:copyTypeElem($type as element(), + $fnRec as function(*), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + $type/element {'z:'||local-name(.)} { + @* ! $fnRec(., $nsmap, $options), + attribute z:typeCategory {u:typeCategory($type)}, + node() ! $fnRec(., $nsmap, $options) + } +}; + +declare function cd:copyOtherElem($elem as element(), + $fnRec as function(*), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + if ($elem/ancestor::xs:documentation) then + $elem/cd:copyElem(., $fnRec, $nsmap, $options) + else error(QName((), 'UNEXPECTED_ELEMENT'), + concat('Unexpected element, local name=', $elem/local-name(.))) +}; + +declare function cd:copyOtherAtt($att as attribute(), + $options as map(xs:string, item()*)?) + as attribute() { + if ($att/ancestor::xs:documentation) then + $att/cd:copyAtt(., $options) + else error(QName((), 'UNEXPECTED_ATTRIBUTE'), + concat('Unexpected attribute,local name=', $att/local-name(.))) +}; + +declare function cd:copyAtt($att as attribute(), + $options as map(xs:string, item()*)?) + as attribute() { + $att/attribute {'z:'||local-name(.)} {.} +}; + +declare function cd:copyNameAtt($name as attribute(name), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as attribute() { + if ($name/parent::xs:attribute[not(parent::xs:schema)]) then + attribute z:name {$name} else + + let $qname := $name/QName(ancestor::xs:schema/@targetNamespace, .) + let $qnameNorm := ns:normalizeQName($qname, $nsmap) + return attribute z:name {$qnameNorm} +}; + +declare function cd:copyQNameAtt($att as attribute(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as attribute() { + let $qname := $att/resolve-QName(., ..) + let $qnameNorm := ns:normalizeQName($qname, $nsmap) + return $att/attribute {'z:'||local-name(.)} {$qnameNorm} +}; + +declare function cd:copyQNameAtt_noDefaultNamespace( + $att as attribute(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as attribute() { + let $qname := + if (not(contains($att, ':'))) then QName((), $att) + else $att/resolve-QName(., ..) + let $qnameNorm := ns:normalizeQName($qname, $nsmap) + return $att/attribute {'z:'||local-name(.)} {$qnameNorm} +}; + +declare function cd:copyQNamesAtt($att as attribute(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as attribute() { + let $qnamesNorm := + for $name in tokenize($att) + let $qname := resolve-QName($name, $att/..) + return ns:normalizeQName($qname, $nsmap) + return $att/attribute {'z:'||local-name(.)} {$qnamesNorm} +}; + +declare function cd:writeTypeAtt($att as attribute(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as attribute()+ { + let $schemas := $options?schemas?* + let $qnameNorm := + resolve-QName($att, $att/..) ! ns:normalizeQName(., $nsmap) + let $typeCategory := $qnameNorm ! u:typeCategory(., $schemas) + return ( + $att/attribute {'z:'||local-name(.)} {$qnameNorm}, + $att/attribute {'z:'||local-name(.)||'Category'} {$typeCategory} + ) +}; + +declare function cd:writeTypeIdAtt($att as attribute(z:typeID), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as attribute()+ { + $att, + u:getLocalTypeLocator($att/.., $nsmap, $options) ! attribute z:typeLocator {.} +}; + +declare function cd:writeOccAtt($comp as element()) + as attribute(z:occ) { + if ($comp/self::attribute()) then + if ($comp/@use eq 'required') then '1:1' else '0:1' + else + + let $minOccurs := ($comp/@minOccurs, '1')[1] + let $maxOccurs := ($comp/@maxOccurs, '1')[1] ! replace(., 'unbounded', '*') + let $occ := $minOccurs||':'||$maxOccurs + return attribute z:occ {$occ} +}; + +(:~ + : Maps an annotation element to an annotation descriptor. + :) +declare function cd:annotationDescriptor($anno as element(xs:annotation)?) + as element(z:annotation)? { + if (not($anno)) then () else + { + $anno/*/element {'z:'||local-name(.)} {node()} + } +}; \ No newline at end of file diff --git a/docs/generate_tables/xco-domain.xqm b/docs/generate_tables/xco-domain.xqm new file mode 100644 index 000000000..4e05d49f3 --- /dev/null +++ b/docs/generate_tables/xco-domain.xqm @@ -0,0 +1,572 @@ +(: + : Functions evaluating domains defined by the customization document. + :) +module namespace dm="http://www.parsqube.de/ns/xco/domain"; + +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; + +import module namespace dg="http://www.parsqube.de/ns/xco/debug" + at "xco-debug.xqm"; + +import module namespace fu="http://www.parsqube.de/ns/xco/file-util" + at "xco-file-util.xqm"; + +import module namespace sd="http://www.parsqube.de/ns/xco/simple-type-description" + at "xco-stype-description.xqm"; + +import module namespace sf="http://www.parsqube.de/ns/xco/string-filter" + at "xco-sfilter.xqm"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +declare variable $dm:findComps := + map{ + 'type': function($domain, $namespace, $name) { + $domain//xsd[@targetNamespace eq $namespace] + //(simpleTypes/simpleType, complexTypes/complexType)[@name eq $name]}, + 'group': function($domain, $namespace, $name) { + $domain//xsd[@targetNamespace eq $namespace] + //groups/group[@name eq $name]}, + 'attributeGroup': function($domain, $namespace, $name) { + $domain//xsd[@targetNamespace eq $namespace] + //attributeGroups/attributeGroup[@name eq $name]}, + 'element': function($domain, $namespace, $name) { + $domain//xsd[@targetNamespace eq $namespace] + //elements/element[@name eq $name]}, + 'attribute': function($domain, $namespace, $name) { + $domain//xsd[@targetNamespace eq $namespace] + //attributes/attribute[@name eq $name]} + }; + +(: + : + : I n t e r f a c e f u n c t i o n s + :) +(:~ + : Returns the file system path of a report with a given report type. + : The file path refers to the main report with that type. In order to + : retrieve the file system path of other parts of a report (e.g. the + : enum dictionary), call 'getReportPartPath'. + + : + : @param reportType a report type + : @param an optional domain element + : @param options options controlling the processing + : @return file system path of the main report with that type + :) +declare function dm:getReportPath($reportType as xs:string, + $domain as element()?, + $options as map(xs:string, item()*)) + as xs:string { + (: Explicit 'ofile' parameter overwrites any domain settings :) + let $ofile := $options?ofile + let $reportTypeFinal := $options?reportType + let $path := + if ($ofile and $reportType eq $reportTypeFinal) then $ofile + + (: No domain - default path depending on 'odir' and the report type :) + else if (not($domain)) then + let $odir := $options?odir + let $fname := dm:reportTypeDefaultFileName($reportType) + return $odir||'/'||$reportType||'/'||$fname + + (: File path is retrieved from the compiled domain element :) + else + let $odir := $options?odir + let $reportDirRelPath := $domain/processing/reportDirRelPath[string()] + let $reportFileBaseName := $domain/processing/reportFileBaseName + let $fileExtension := dm:reportTypeFileNameExtension($reportType) + let $relPath := $reportDirRelPath ! concat(., '/') + return $odir||'/'||$reportType||'/'||$relPath|| + $reportFileBaseName||'.'||$fileExtension + (: let $_DEBUG := trace($path, 'RPATH FOR: ***RTYPE='||$reportType||';DOM='||$domain/@name||': ') :) + return $path +}; + +(:~ + : Returns the file system path of a report with a given report type + : and containing a part of the report with a given part name. + : + : @param reportType a report type + : @param reportPart a named part of the reporgt, e.g. 'enum-dict' + : @param an optional domain element + : @param options options controlling the processing + : @return file system path of the main report with that type + :) +declare function dm:getReportPartPath($reportType as xs:string, + $reportPart as xs:string?, + $domain as element()?, + $options as map(xs:string, item()*)) + as xs:string { + let $mainReportPath := dm:getReportPath($reportType, $domain, $options) + return + if (not($reportPart)) then $mainReportPath + else fu:insertLabelBeforeFileNameExtension($mainReportPath, '.'||$reportPart) +}; + +(:~ + : Returns the file system path of an input report file. + :) +declare function dm:getInputReportPath($inputReportType as xs:string, + $inputReportBaseDir as xs:string, + $domain as element(), + $options as map(xs:string, item()*)) + as xs:string { + let $reportDirRelPath := $domain/processing/reportDirRelPath + let $reportFileBaseName := $domain/processing/reportFileBaseName + let $reportFileExtension := dm:reportTypeFileNameExtension($inputReportType) + return fu:applyRelPath($inputReportBaseDir, $reportDirRelPath) + ||'/'||$reportFileBaseName||'.'||$reportFileExtension +}; + +(:~ + : Returns the default file name for a given report type. + : + : @param reportType a report type + : @return the default file name + :) +declare function dm:reportTypeDefaultFileName($reportType as xs:string) + as xs:string { + switch($reportType) + case 'contab' return 'contab.html' + default return $reportType||'.xml' +}; + +(:~ + : Returns the default file name for a given report type. + : + : @param reportType a report type + : @return the default file name + :) +declare function dm:reportTypeFileNameExtension($reportType as xs:string) + as xs:string { + switch($reportType) + case 'contab' return 'html' + default return 'xml' +}; + +(: + : + : C o n s t r u c t d o m a i n e l e m e n t s + :) + +(:~ + : Evaluates the definition of domains, returning an extended + : representation. + : + : @param custom the customization document + : @param schemas the schema elements to be reported + : @return an element describing all domains + :) +declare function dm:constructDomains($customDomains as element()?, + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as element(domains)? { + let $domainsParam := $options?domains + return if (not($domainsParam) and not($customDomains)) then () else + + let $schemaDescriptors := $schemas/dm:xsdDescriptor(.) + let $domainElems := $customDomains/* + let $tnsDomains := $domainElems[content/foreach = 'targetNamespace'] + let $xsdDomains := $domainElems[content/foreach = 'xsd'] + let $filterDomains := $domainElems except ($tnsDomains, $xsdDomains) + return + if ($tnsDomains) then + error((), 'Customized target namespace domains not yet supported.') + else if ($xsdDomains) then + error((), 'Customized XSD domains not yet supported.') + else + if ($domainsParam eq 'xsd') then + dm:createXsdDomains($schemaDescriptors, $options) + else + let $domains := + if (not($filterDomains)) then () else + dm:compileFilterDomains($schemaDescriptors, $filterDomains, $options) + return + {$domains} +}; + +(: + : + : C o m p i l e f i l t e r d o m a i n s + :) +(:~ + : Compiles custom domain defintions, type "filter domain". + :) +declare function dm:compileFilterDomains( + $schemaDescriptors as element()*, + $customDomains as element()+, + $options as map(xs:string, item()*)) + as element(domain)* { + let $activeDomains := $options?activeDomains + + for $domain at $pos in $customDomains + where empty($activeDomains) or $domain/@name = $activeDomains + let $tnsPlus := + $domain/content/targetNamespace/ + dm:filterSchemaDescriptorsByTns(., $schemaDescriptors) + let $tnsMinus := + $domain/content/exceptTargetNamespace/ + dm:filterSchemaDescriptorsByFiles(., $schemaDescriptors) + let $filesPlus := $domain/content/files/ + dm:filterSchemaDescriptorsByFiles(., $schemaDescriptors) + let $filesMinus := $domain/content/exceptFiles/ + dm:filterSchemaDescriptorsByFiles(., $schemaDescriptors) + let $selected := ($tnsPlus, $filesPlus) + [not(. = ($tnsMinus, $filesMinus))] + let $selectedOrdered := + dm:sortSchemaDescriptors($selected, $domain) + let $id := 'd'||$pos + let $name := ($domain/@name, $id)[1] + let $summary := $domain/dm:filterDomainSummary(.) + return + { + { + $selectedOrdered + }, + dm:compileProcessingElem($domain/processing, $options) + } +}; + +(:~ + : Filters schema descriptors by target namespace. + :) +declare function dm:filterSchemaDescriptorsByTns( + $tns as xs:string, + $schemaDescriptors as element()*) + as element()* { + let $sfilter := sf:compileStringFilter($tns) + return + $schemaDescriptors + [sf:matchesStringFilter(string(@targetNamespace), $sfilter)] +}; + +(:~ + : Filters schema descriptors by file name/path constraints. + :) +declare function dm:filterSchemaDescriptorsByFiles( + $files as element(), + $schemaDescriptors as element()*) + as element()* { + let $dir := $files/@dir + let $name := $files/@name + let $nameFilter := sf:compileStringFilter($name) + let $deep := $files/@deep/xs:boolean(.) + let $dirFilter := + if (starts-with($dir, '/')) then + if ($deep) then $dir||'(/.*)?$' + else $dir||'$' + else if ($deep) then '(.*/)?'||$dir||'(/.*/)?$' + else '(.*/)?'||$dir||'$' + return + for $schemaDesc in $schemaDescriptors + where sf:matchesStringFilter($schemaDesc/@fileName, $nameFilter) + let $folder := $schemaDesc/@filePath ! file:parent(.) ! u:normalizeUri(., ()) + where matches($folder, $dirFilter, 'i') + return $schemaDesc +}; + +declare function dm:filterDomainSummary($domain as element()) + as xs:string { + let $tns := $domain/content/targetNamespace/concat('tns=', .) => string-join(', ') + let $etns := $domain/content/exceptTargetNamespace/concat('~tns=', .) => string-join(', ') + let $files := $domain/content/files/ + concat('files=[dir=', @dir, ', name=', @name, ', deep=', (@deep, 'false')[1], ']') + => string-join(', ') + let $efiles := $domain/content/exceptFiles/ + concat('~files=[dir=', @dir, ', name=', @name, ', deep=', (@deep, 'false')[1], ']') + => string-join(', ') + return string-join(($tns, $etns, $files, $efiles)[string()], '; ') +}; + +(: + : + : C o m p i l e c u s t o m d o m a i n s + :) +(:~ + : Copiles the processing element of custom domain elements. + :) +declare function dm:compileProcessingElem($processing as element(processing), + $options as map(xs:string, item()*)) + as element(processing) { + $processing ! dm:compileProcessingElemREC(., $options) +}; + +(:~ + : Recursive helper function of `compileProcessingElem`. + :) +declare function dm:compileProcessingElemREC($n as node(), + $options as map(xs:string, item()*)) + as node()* { + typeswitch($n) + case document-node() return document {$n/node() ! dm:compileProcessingElemREC(., $options)} + (: Add elements: , :) + case element(processing) return + let $reportType := $options?reportType + let $reportDirRelPath := ($n/reportDirRelPath, '')[1] + let $forEachDomain := ($options?forEachDomain, false())[1] + return + element {node-name($n)} { + $n/@* ! dm:compileProcessingElemREC(., $options), + $n/node() ! dm:compileProcessingElemREC(., $options), + {$forEachDomain}, + {$reportDirRelPath} + } + case element(reportDirRelPath) return () (: already processed :) + case element(title) return + let $value := normalize-space($n) + let $title := + if (starts-with($value, '#')) then + let $key := $value ! substring(., 2) + return $options($key) + else $value + return {$title} + case element() return + element {node-name($n)} { + $n/@* ! dm:compileProcessingElemREC(., $options), + $n/node() ! dm:compileProcessingElemREC(., $options) + } + case attribute() return $n + default return $n +}; + +(: + : + : C r e a t e X S D d o m a i n s + :) +(:~ + : Creates XSD domains, one for each XSD. + : + : @param schemaDescriptors schema descriptors + : @param options options controlling the processing + : @return XSD domains + :) +declare function dm:createXsdDomains($schemaDescriptors as element()*, + $options as map(xs:string, item()*)) + as element() { + let $odir := $options?odir + let $dir := $options?dir + return + (: Check should have been performed before - here only minimal check :) + if (not($odir) or not($dir)) then error() else + + let $sortedSchemaDescriptors := + for $schemaDesc in $schemaDescriptors + let $filePath := $schemaDesc/@filePath + order by $filePath + return $schemaDesc + + let $domains := + for $schemaDesc at $pos in $sortedSchemaDescriptors + let $id := 'd'||$pos + let $filePath := $schemaDesc/@filePath + let $fileRelPath := fu:getRelPath($dir, $filePath) + let $fileName := $filePath ! file:name(.) + let $relParentPath := $fileRelPath ! fu:getRelParentPath(.) + let $dirInfo := $relParentPath[string()] ! {.||'/ '} + let $dirPath := $filePath ! fu:getParentPath(.) + let $dirRelPath := fu:getRelPath($dir, $dirPath) + let $fname := $schemaDesc/@fileName + let $fileBaseName := $fname ! fu:removeFileExtension(.) + return + { + {$schemaDesc}, + + {'Contents: ', $dirInfo, $fileName} + {'Enumeration dictionary: '||$fileRelPath} + {$fileBaseName} + {$dirRelPath} + + } + return + { + $domains + } +}; + +(: + : D o m a i n r e l a t e d u t i l i t i e s + :) + +(:~ + : Maps the domains to a sequence of maps, each one containing + : a domain element and the components belonging to that domain. + : + : Map structure: + : { + : 'domain': ... + : 'comps': ..., ..., ... + : } + : + : @param comps schema components + : @param domains domain elements, defining domains + : @param schemas the schemas to be evaluated + : @param options options controlling the processing + : @return a sequence of maps + :) +declare function dm:getDomainComponentMaps( + $comps as element()*, + $domains as element(domain)*, + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as map(xs:string, item()*)* { + let $xsdDict := + map:merge( + for $comp in $comps + let $xsdpath := $comp/base-uri(.) ! u:normalizeUri(., ()) + group by $xsdpath + return map:entry($xsdpath, $comp) + ) + for $domain in $domains + let $domainComps := + for $xsd in $domain/content/xsd + let $filePath := $xsd/@filePath ! u:normalizeUri(., ()) + let $xsdComps := $xsdDict($filePath) + return $xsdComps + return + map{'domain': $domain, 'comps': $domainComps} +}; + +(:~ + : Maps the domains to a sequence of maps, each one containing + : a domain element and the corresponding components, grouped + : by containing XSD. + : + : Map structure: + : { + : 'domain': ... + : 'xsds': + : $filePath: ..., ..., ... + : } + : + : @param comps schema components + : @param domains domain elements, defining domains + : @param schemas the schemas to be evaluated + : @param options options controlling the processing + : @return a sequence of maps + :) +declare function dm:getDomainXsdComponentMaps( + $comps as element()*, + $domains as element(domain)*, + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as map(xs:string, item()*)* { + (: map: xsd-path => components :) + let $xsdDict := + map:merge( + for $comp in $comps + let $xsdpath := $comp/base-uri(.) ! u:normalizeUri(., ()) + group by $xsdpath + return map:entry($xsdpath, $comp) + ) + for $domain in $domains + let $xsdComps := map:merge( + for $xsd in $domain/content/xsd + let $filePath := $xsd/@filePath ! u:normalizeUri(., ()) + let $xsdComps := $xsdDict($filePath) + return map:entry($filePath, $xsdComps)) + return + map{'domain': $domain, 'xsds': $xsdComps} +}; + + +(: + : + : U t i l i t y f u n c t i o n s + :) + +(:~ + : Maps an XSD to an element summarizing XSD properties and + : content. + :) +declare function dm:xsdDescriptor($schema as element(xs:schema)) + as element() { + let $filePath := $schema/base-uri(.) ! u:normalizeUri(., ()) + let $fileName := $filePath ! file:name(.) + let $tns := $schema/@targetNamespace + let $stypes := $schema/xs:simpleType/@name/string() => sort() + let $ctypes := $schema/xs:complexType/@name/string() => sort() + let $elements := $schema/xs:element/@name/string() => sort() + let $attributes := $schema/xs:attribute/@name/string() => sort() + let $groups := $schema/xs:group/@name/string() => sort() + let $attributeGroups := $schema/xs:attributeGroup/@name/string() => sort() + return + { + { + $elements ! + }, + { + $attributes ! + }, + { + $stypes ! + }, + { + $ctypes ! + }, + { + $groups ! + }, + { + $attributeGroups ! + } + } +}; + +(:~ + : Sort schema descriptors. A schema descriptor is an element + : with an attribute @filePath, containing the file path of + : a schema. + :) +declare function dm:sortSchemaDescriptors( + $schemaDescriptors as element()*, + $domain as element(domain)) + as element()* { + let $first := $domain/processing/order/first + let $last := $domain/processing/order/last + return + if (not(($first, $last))) then + for $sd in $schemaDescriptors + order by $sd/@filePath/lower-case(.) + return $sd + else + + $schemaDescriptors + => dm:sortSchemaDescriptorsFirstOrLast($first) + => dm:sortSchemaDescriptorsFirstOrLast($last) +}; + +(:~ + : Sorts a sequence of schema descriptors (1) by the position of + : a matching file path in $firstOrLast, (2) by file path. + :) +declare function dm:sortSchemaDescriptorsFirstOrLast( + $schemaDescriptors as element()*, + $firstOrLast as element()?) + as element()* { + if (not($firstOrLast)) then $schemaDescriptors else + + let $defaultPos := if ($firstOrLast/self::first) then 100000 else 0 + for $sd in $schemaDescriptors + let $filePath := $sd/@filePath + let $pos := + let $match := $firstOrLast/xsd[matches($filePath, '(^|/)'||@filePath, 'i')] + return + if (not($match)) then $defaultPos + else count($match/preceding-sibling::xsd) + 1 + (: let $_DEBUG := trace('pos='||$pos||' filePath='||$filePath) :) + order by $pos, $filePath + return $sd +}; diff --git a/docs/generate_tables/xco-edesc-util.xqm b/docs/generate_tables/xco-edesc-util.xqm new file mode 100644 index 000000000..1c645112d --- /dev/null +++ b/docs/generate_tables/xco-edesc-util.xqm @@ -0,0 +1,545 @@ +(: + : xco-comp-descriptor - functions creating component descriptors + :) +module namespace eu="http://www.parsqube.de/ns/xco/edesc-util"; + +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; +import module namespace cu="http://www.parsqube.de/ns/xco/custom" + at "xco-custom.xqm"; +import module namespace dg="http://www.parsqube.de/ns/xco/debug" + at "xco-debug.xqm"; +import module namespace dm="http://www.parsqube.de/ns/xco/domain" + at "xco-domain.xqm"; +import module namespace ln="http://www.parsqube.de/ns/xco/link" + at "xco-link.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; +import module namespace sd="http://www.parsqube.de/ns/xco/simple-type-description" + at "xco-stype-description.xqm"; +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Returns a table summarizing a set of simple type descriptors. The table is + : designed to support the creation of an HTML table. + : + : @param stypes a sequence of simple type descriptors + :) +declare function eu:stypesTable($stypes as element()*, + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element() { + if (empty($stypes)) then () else + + let $custom := $options?custom + let $stypes := + { + for $stype in $stypes + let $typeQName := $stype/@z:name/resolve-QName(., ..) + let $typeName := string($typeQName) + let $typeId := $stype/@z:typeID + let $typeLabel := $stype/ u:getDescriptorLocalTypeLabel(.) + let $displayName := + if ($typeLabel) then $typeLabel + else + cu:customComponentName( + $typeName, 'simpleType', 'sub', 'contab', $domain/@id, $custom) + let $divId := if ($typeName) then 'type.'||$typeName else 'local-type.'||$typeId + let $tdesc := $stype/@z:typeDesc/string() + let $isEnum := sd:isTypeDescriptionEnumDesc($tdesc) + let $tdetail := + if (not($isEnum)) then $tdesc + else + for $enum in $stype//z:enumeration + return + + let $anno := $stype/z:annotation/z:documentation/normalize-space(.) + let $linkName := + (: Linking to enum dictionary switched off :) + if (not($isEnum) or true()) then () + else if ($typeId) then ln:getLocalEnumTypeLinkRef($domain, $typeId, $options) + else ln:getTypeLinkRef($domain, $typeQName, $tdesc, $options) + let $lname := ($typeName ! replace(., '.+:', ''), $typeLabel)[1] + let $globalOrLocal := if ($typeId) then 2 else 1 + order by $globalOrLocal, $lname + return + { + { + $linkName ! attribute linkName {.}, + $displayName + }, + {$tdetail}, + {$anno} + } + } + + let $_DEBUG := dg:WRITE_FILE($stypes, 'STYPES.xml', 'stypes', $domain/@name, $options) + return $stypes +}; + +(:~ + : Returns a table summarizing the contents of a schema component. + : The table is designed to support the creation of an HTML + : table. + :) +declare function eu:contentTable($comp as element(), + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element() { + let $custom := $options?custom + let $compKind := $comp/local-name(.) + let $type := $comp/@z:type + return + if ($compKind eq 'element' and $type) then + eu:contentTableForTypedElement($comp, $domain, $options) + else + + let $typeQName := $type/resolve-QName(., ..) + let $isTypeBuiltin := boolean(ns:isQNameBuiltin($typeQName)) + let $typeLinkName := $typeQName ! ln:getTypeLinkRef($domain, ., (), $options) + let $name := $comp/@z:name/string() + let $lname := $name ! replace(., '.+:', '') + let $typeId := $comp/@z:typeID/string() + let $typeLabel := $comp[self::z:complexType]/ + @z:typeLocator ! concat(., ' (', $typeId, ')') + let $ident := ($typeId, $lname)[1] + + (: *** Function items :) + (: Determines the relevant group name :) + let $fnGroup := function($e) {$e/ancestor::*:group[1]/@z:name/resolve-QName(., ..)} + (: Each "part" corresponds to a level of type derivation; + in case of a group, there is only one level corresponding + to the complete group :) + let $parts := ( + if ($comp/self::z:group) then $comp + else + let $typeComp := + if ($comp/self::z:element) then $comp/(z:complexType, z:simpleType) + else if ($comp/(self::z:complexType, self::z:simpleType)) then $comp + else $comp + return + if (not($typeComp/z:baseType)) then $typeComp + else ($typeComp/(z:baseType, z:restriction, z:extension))) + + (: Each "table part" is an element describing the content + of a part. + :) + let $tableParts := + (: Last restriction - extensions before it do not contribute elements :) + let $lastRestrictionPart := $parts[self::z:restriction][last()] + + for $part at $pos in $parts + let $atts := $part/(z:attribute, z:attributeGroup/z:attribute) + let $elems := + $part[not(. << $lastRestrictionPart)] + /descendant::z:element[not(ancestor::z:element[. >> $comp])] + + let $attRows := {$atts/eu:contentTable_attRow(., $domain, $options)}[$atts] + let $groups := + for tumbling window $grouped in $elems + start $start previous $previous when + let $g1 := $previous/$fnGroup(.) + let $g2 := $start/$fnGroup(.) + return $g1 ne $g2 or count(($g1, $g2)) eq 1 or not($previous) + let $gname := $start/$fnGroup(.) + (: $startedChoices - + for each element an array containing the started choice elems :) + let $startedChoices := array{ + for $elem in $grouped + let $sc := $elem/eu:getStartedChoices(.) + return array{$sc} + } + let $countStartedChoices := + (: Use tail, as choice text line is displayed before the group :) + count(array:tail($startedChoices)?*[array:size(.) gt 0]) + return + { + for $elem at $pos in $grouped + return + $elem/eu:contentTable_elemRow( + ., $pos, count($grouped), $gname, $startedChoices($pos), + $countStartedChoices, $domain, $options) + } + let $partElemName := + if ($compKind eq 'group') then 'groupContent' + else if ($pos eq count($parts)) then 'typeContent' + else 'baseTypeContent' + return + element {$partElemName} { + $part/@z:name/attribute name {.}, + attribute isRestriction {'yes'} [$part is $lastRestrictionPart], + $attRows, + $groups + } + let $baseType := ($tableParts/self::baseTypeContent)[last()]/@name + let $baseTypeQName := $baseType/resolve-QName(., $comp) + let $isBaseTypeBuiltin := $baseTypeQName ! ns:isQNameBuiltin(.) + let $baseTypeLinkName := $baseTypeQName ! ln:getTypeLinkRef($domain, ., (), $options) + let $anno := $parts[z:annotation/z:documentation][last()]/ + z:annotation/z:documentation/normalize-space(.) + let $table := + { + $name ! attribute name {.}, + $typeId ! attribute typeID {.}, + $typeLabel ! attribute typeLabel {.}, + $baseType ! attribute baseName {.}, + $baseTypeLinkName ! attribute baseLinkName {.}, + {$anno}, + { + for $prefix in $comp/in-scope-prefixes(.) return + namespace {$prefix} {namespace-uri-for-prefix($prefix, $comp)}, + $tableParts + } + } + let $_DEBUG := dg:WRITE_FILE($table, 'CONTENT_TABLE.xml', + 'content_table', $ident, $options) + return $table +}; + +(:~ + : Write a content table row describing an element. + :) +declare function eu:contentTable_elemRow( + $elem as element(), + $itemPos as xs:integer, + $groupSize as xs:integer, + $groupQName as xs:QName?, + $startedChoices as array(element(z:choice)+)?, + $countGroupMembersWithStartedChoices as xs:integer, + $domain as element()?, + $options as map(xs:string, item()*)) + as element(row) { + let $fnChoiceBranchNumberPath := function($n) { + $n/ancestor-or-self::*[parent::z:choice] + /u:letterNumber(1 + count(eu:precedingSiblingNonAnno(.))) + => string-join('') + } + + (: Group column :) + let $groupCol := + if (empty($groupQName)) then + else if ($itemPos gt 1) then () + else + { + string($groupQName) + } + + (: Branch column :) + let $branchCol := + $elem/$fnChoiceBranchNumberPath(.)[.] ! {.} + + (: The name colspan depends on the presence of a group :) + let $nameColspan := if ($branchCol) then 1 else 2 + let $type := $elem/@z:type + let $typeId := $elem/@z:typeID + let $typeIdDisplay := $typeId ! concat('local-type: ', .) + let $typeQName := $type/resolve-QName(., ..) + let $tdesc := $elem/@z:typeDesc + let $typeCategory := $elem/@z:typeCategory + let $isTypeSimple := $typeCategory/u:isTypeCategorySimple(.) + let $isTypeBuiltin := boolean(ns:isQNameBuiltin($typeQName)) + let $typeLinkName := + if ($type) then + ln:getTypeLinkRef($domain, $typeQName, $tdesc[$isTypeSimple], $options) + else if ($typeId) then + ln:getLocalTypeLinkRef($domain, $typeId, $tdesc[$isTypeSimple], $options) + else + let $_DEBUG := trace($elem/eu:edescItemPath(.), '*** Item without type, path: ') + return () + let $elemLinkName := + if (not($elem/@z:reference eq 'yes')) then () + else $elem/@z:name ! ln:getLinkRef($domain, 'element', resolve-QName(., ..), $options) + let $startChoice := ( + array:flatten($startedChoices)/eu:getChoiceSummary(.) => string-join('; ') + )[string()] + return + { + (: The @startChoice attribute will trigger a text line similar to + "The element contains one of ..." :) + $startChoice ! attribute startChoice {.}, + $groupCol, + $branchCol, + { + $elemLinkName ! attribute linkName {.}, + $elem/@z:name/string() + }, + {$elem/@z:occ/string()}, + { + $typeLinkName ! attribute linkName {.}, + ($type/string(), $typeIdDisplay) + }, + {$elem/z:annotation/z:documentation/normalize-space(.)} + } +}; + +(:~ + : Write a content table row describing an attribute. + :) +declare function eu:contentTable_attRow($att, + $domain, + $options as map(xs:string, item()*)) + as element(row) { + let $nameColspan := 2 + let $type := $att/@z:type + let $typeQName := $type/resolve-QName(., ..) + let $isTypeBuiltin := boolean(ns:isQNameBuiltin($typeQName)) + let $isSimpleType := $att/@z:typeCategory/starts-with(., 's') + let $typeLinkName := $typeQName + ! ln:getTypeLinkRef($domain, ., $att/@z:typeDesc[$isSimpleType], $options) + return + { + , + {'@'||$att/@z:name/string()}, + {$att/@z:occ/string()}, + { + $typeLinkName ! attribute linkName {.}, + $type/string() + }, + {$att/z:annotation/z:documentation/normalize-space(.)} + } +}; + + +(:~ + : Returns a table summarizing the contents of a schema content. + : The table is designed to support the creation of an HTML + : table. + :) +declare function eu:contentTableForTypedElement($comp as element(), + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element() { + let $compKind := 'element' + let $custom := $options?custom + let $type := $comp/@z:type + let $typeQName := $type/resolve-QName(., ..) + let $isTypeBuiltin := boolean(ns:isQNameBuiltin($typeQName)) + let $isTypeSimple := $comp/@z:typeCategory/u:isTypeCategorySimple(.) + let $typeLinkName := $typeQName + ! ln:getTypeLinkRef($domain, ., $comp/@z:typeDesc[$isTypeSimple], $options) + let $name := $comp/@z:name/string() + return + { + let $compDisplayName := cu:customComponentName( + $name, $compKind, 'main', 'contab', $domain/@id, $custom) + let $typeDisplayName := cu:customComponentName( + $type, 'complexType', 'sub', 'contab', $domain/@id, $custom) + let $anno := $comp/z:annotation/z:documentation/normalize-space(.) + let $sgroup := $comp/@z:substitutionGroup/string() + return + { + { + {$compDisplayName}, + { + $typeLinkName ! attribute linkName {.}, + $typeDisplayName + }, + {$anno} + } + } + } +}; + +(:~ + : Returns the immediately enclosing z:choice elements whose first branch starts + : with element $elem. A choice element is "immediately enclosing" if $elem is + : not contained by an element contained by the choice. + :) +declare function eu:getStartedChoices($elem as element()) + as element(z:choice)* { + let $firstChoiceAnc := $elem/ancestor::z:choice[1] + where $firstChoiceAnc + let $firstElemAnc := $elem/ancestor::z:element[1] + where not($firstElemAnc >> $firstChoiceAnc) + where + (: The element and enclosing elements within the enclosing choice branch element + (e.g. a z:sequence element) must not be preceded by other elements. + :) + every $anc in $elem/ancestor-or-self::*[. >> $firstChoiceAnc] satisfies + $anc/empty(preceding-sibling::*[not(self::z:annotation)]) + let $containingBranchElem := $firstChoiceAnc/ancestor-or-self::*[parent::z:choice][1] + return ( + $firstChoiceAnc/eu:getStartedChoices(.) + [$containingBranchElem/empty(eu:precedingSiblingNonAnno(.))], + $firstChoiceAnc + ) +}; + +(:~ + : Returns the preceding siblings except z:annotation elements. + :) +declare function eu:precedingSiblingNonAnno($elem as element()) + as element()* { + $elem/(preceding-sibling::* except preceding-sibling::z:annotation) +}; + +(:~ + : Returns the child elements except z:annotation elements. + :) +declare function eu:childElemsNonAnno($elem as element()) + as element()* { + $elem/(* except z:annotation) +}; + +(: + : F u n c t i o n s s u m m a r i z i n g c h o i c e s + :) + +(:~ + : Returns a summary of a choice element. The summary is a ; + : concatenated list of up to three items: + : - elems=... + : which branches (a, b, c, ...) correspond to a single element; + : examples: elems=a-d, elems=a,d + : - seqs=... + : which branches correspond to a sequence of elements + : examples: seqs=a-d, seqs=a,d + : - contextbranch=... + : If the choice corresponds to a branch of a parent choice, the + : "path" of ancestor branches; + : examples: contextbranch=b, contextbranch=ba + : If a contextbranch exists, the branch labels reported in elems= + : and seqs= are preceded by the contextbranch. Examples: + : contextbranch=b, elems=ba-bc, seqs=bd + : contextbranch=ba, elems=baa-bac, seqs=bad + : + : @param choice a choice element from an extended component descriptor + : @return the choice summary + :) +declare function eu:getChoiceSummary($choice as element(z:choice)) + as xs:string { + let $fnChoiceBranchNumberPath := function($n) { + let $elemAnc1 := $n/ancestor::z:element[1] return + $n/ancestor-or-self::*[not(. >> $elemAnc1)][parent::z:choice] + /u:letterNumber(1 + count(eu:precedingSiblingNonAnno(.))) + => string-join('') + } + + let $fnPosString := function($positions, $prefix) { + if (not($positions)) then () + else if (contains('a b c d e f g h i j k l m n o p q r s t u v w', + $positions)) + then + let $seq := tokenize($positions) + return + if (count($seq) eq 1) then $prefix||$seq + else $prefix||$seq[1]||'-'||$prefix||$seq[last()] + else tokenize($positions) ! $prefix||. => string-join(',') + } + + let $choicePositionPrefix := $choice/$fnChoiceBranchNumberPath(.) + let $branchKinds := + for $child at $pos in $choice/eu:childElemsNonAnno(.) + let $posLetter := u:letterNumber($pos) + let $branchKind := $child/eu:getChoiceBranchKind(.) + return $branchKind||'~'||$posLetter + let $elemBranches := + $branchKinds[starts-with(., 'elem')] ! substring-after(., '~') + => string-join(' ') + let $sequenceBranches := + $branchKinds[starts-with(., 'sequence')] ! substring-after(., '~') + => string-join(' ') + let $result := string-join(( + $elemBranches[string()] ! $fnPosString(., $choicePositionPrefix) ! concat('elems=', .), + $sequenceBranches[string()] ! $fnPosString(., $choicePositionPrefix) ! concat('seqs=', .), + $choicePositionPrefix[string()] ! concat('contextbranch=', .) + ), ', ') + return $result +}; + +(:~ + : Returns the kind of a choice branch, which is 'elem' or + : 'sequence'. A non-recursive call should provide as argument + : a child element of a z:choice element. + :) +declare function eu:getChoiceBranchKind($elem as element()) + as xs:string { + typeswitch($elem) + case element(z:element) return 'elem' + case element(z:sequence) return + let $children := eu:childElemsNonAnno($elem) + return + if (count($children) gt 1) then 'sequence' + else if ($elem/z:element) then 'elem' + else $children/eu:getChoiceBranchKind(.) + case element(z:all) return 'all' + case element(z:annotation) return () + case element(z:choice) | element(z:group) return + let $childKinds := $elem/eu:childElemsNonAnno(.)/eu:getChoiceBranchKind(.) + return + if ($childKinds = 'sequence') then 'sequence' + else if ($childKinds = 'elem') then 'elem' + else error() + default return error() +}; + +(:~ + : Returns the simple type definitions of enum types used by an + : edesc report. + : + : @param report an edesc report + : @return a sequence of type descriptors + :) +declare function eu:getEdescReportEnumTypes($report as element()) + as element(z:simpleType)* { + let $enumTypes1 := $report//z:components/z:simpleType[.//z:enumeration] + let $enumTypes2 := + for $stype in + $report//z:components/(* except z:simpleType) + //z:simpleType[.//z:enumeration][not(ancestor::z:simpleType)] + let $typeId := $stype/@z:typeID + group by $typeId + return $stype[1] + return ($enumTypes1, $enumTypes2) +}; + +(:~ + : Returns the simple type definitions used by an edesc report. + : + : @param report an edesc report + : @return a sequence of type descriptors + :) +declare function eu:getEdescReportSimpleTypes($report as element()) + as element(z:simpleType)* { + let $enumTypes1 := $report//z:components/z:simpleType + let $enumTypes2 := + for $stype in + $report//z:components/(* except z:simpleType) + //z:simpleType[not(ancestor::z:simpleType)] + let $typeId := $stype/@z:typeID + group by $typeId + return $stype[1] + return ($enumTypes1, $enumTypes2) +}; + +(:~ + : Returns a data path of an extended descriptor node representing an element + : or attribute. The path identifies the containing global component and the + : element/attribute path leading to the item. + :) +declare function eu:edescItemPath($item as element()) + as xs:string { + let $globalComp := + $item/ancestor-or-self::*[parent::z:components or position() eq last()][1] + let $globalCompName := $globalComp/@z:name/concat('name=', .) + let $globalCompId := $globalComp/@z:typeID/concat('typeID=', .) + let $globalCompIdent := ($globalCompName, $globalCompId)[1] + let $globalCompKind := $globalComp/local-name() + let $withinCompPath := + $item/ancestor-or-self::*[self::z:element, self::attribute] + [. >> $globalComp]/concat(self::z:attribute()/'@', @z:name) + => string-join('/') + return + string-join(( + $globalCompKind||'['||$globalCompIdent||']', + $withinCompPath[string()] + ), '/') + +}; diff --git a/docs/generate_tables/xco-edesc.xqm b/docs/generate_tables/xco-edesc.xqm new file mode 100644 index 000000000..a5c41f02c --- /dev/null +++ b/docs/generate_tables/xco-edesc.xqm @@ -0,0 +1,767 @@ +(: + + : xco-comp-descriptor - functions creating expanded component descriptors. + :) +module namespace ed="http://www.parsqube.de/ns/xco/edesc"; + +import module namespace rd="http://www.parsqube.de/ns/xco/rdesc" + at "xco-rdesc.xqm"; +import module namespace cd="http://www.parsqube.de/ns/xco/desc" + at "xco-desc.xqm"; +import module namespace cn="http://www.parsqube.de/ns/xco/comp-names" + at "xco-comp-names.xqm"; +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; +import module namespace dc="http://www.parsqube.de/ns/xco/dcache" + at "xco-dcache.xqm"; +import module namespace dm="http://www.parsqube.de/ns/xco/domain" + at "xco-domain.xqm"; +import module namespace eu="http://www.parsqube.de/ns/xco/edesc-util" + at "xco-edesc-util.xqm"; +import module namespace fu="http://www.parsqube.de/ns/xco/file-util" + at "xco-file-util.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; +import module namespace sd="http://www.parsqube.de/ns/xco/simple-type-description" + at "xco-stype-description.xqm"; +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(: + : P r o c e s s i n g d o m a i n s a n d s e q u e n c e s + : ================================================================== + :) + +(:~ + : Writes for each domain an edesc report file. + : + : Care is taken to fill and use a cache containing expanded + : component descriptors. To achieve this, a nested fold-left + : processing is used, in which the cache is part of the + : accumulators (outer and inner level). + : + : @param comps schema components + : @param nsmap a map of namespace bindings + : @param schemas the schemas to be evaluated + : @param options options controlling the processing + : @return empty sequence + :) +declare function ed:writeExpandedCompDescsPerDomain( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as item()? { + let $domains := $options?domains/domain + return if (not($domains)) then () else + + (: Optimization - process all simple types first :) + let $stypes := $comps/self::xs:simpleType + let $_OPTIM := + if (count($stypes) gt 10) then + let $_DEBUG := trace('*** Optimization - cache all simple types ('||count($stypes)||')') + let $_ACTION := ed:foldLeftGetExpandedCompDescs($stypes, $nsmap, $schemas, $options) + let $_DEBUG := trace('*** Optimization finished') + return () + + (: Create a sequence of "domain - component maps" describing the domains: + : domain: domain-element + : comps: component elements + : These maps are used as items (!) by fold-left processing. + :) + let $domainCompMaps := dm:getDomainComponentMaps($comps, $domains, $schemas, $options) + + (: fold-left processing of the maps :) + let $fnProcessDomain := function($accum, $domainCompMap) { + let $options := $accum?options + let $domain := $domainCompMap?domain + let $comps := $domainCompMap?comps + + (: Nested fold-left processing :) + let $nestedAccum := ed:foldLeftGetExpandedCompDescs($comps, $nsmap, $schemas, $options) + (: Updated options (containing updated cache) :) + let $options2 := $nestedAccum?options + (: Extract and augment expanded component descriptors :) + let $edescs := + let $prelim := $nestedAccum?edesc + return ed:getExpandedCompDescs_addTypeDescriptions($prelim, $options2) + + (: Updated accumulator contains updated options containing updated cache :) + let $accum2 := map:put($accum, 'options', $options2) + + (: Create schema reports: + : descriptors are grouped by schema and wrapped in schema elements :) + let $schemaReports := + for $edesc in $edescs + group by $baseUri := $edesc/base-uri(.) ! u:normalizeUri(., ()) + return + { + if ($options?skipAnno) then () else + let $schema := $schemas[base-uri(.) eq $baseUri] + return $schema/xs:annotation[1]/cd:annotationDescriptor(.), + {$edesc} + } + + (: Sort schema reports :) + let $schemaReports := dm:sortSchemaDescriptors( + $schemaReports, + $domain) + (: + $domain/processing/order/first, + $domain/processing/order/last) + :) + + (: Create domain report: + : schema reports are wrapped in a domain element :) + let $domainReport := + let $prelim := + { + $schemaReports + } + /ns:addNamespaceContext(., $nsmap, ()) + /u:prettyNode(.) + return + if ($options?skipAnno) then $prelim/u:removeAnno(.)/u:prettyNode(.) + else $prelim + let $reportFilePath := dm:getReportPath('edesc', $domain, $options) + let $_LOG := trace('*** Write edesc report: '||$reportFilePath) + let $_WRITE := u:writeXmlDoc($reportFilePath, $domainReport) + return $accum2 + } + + (: Initialize accumulator for fold-left processing of domains :) + let $accum := + map{'options': $options, + 'counter': 1, + 'nsmap': $nsmap, + 'schemas': $schemas} + let $finalAccum := fold-left($domainCompMaps, $accum, $fnProcessDomain) + let $options := $finalAccum?options + return $options +}; + +(:~ + : Maps schema components to expanded component descriptors. Uses + : fold-left and returns the accumulator, a map with two keys: + : 'edesc' - the component descriptors, 'options' - the updated + : options map. The options map is updated by updating the cache + : of expanded component descriptors. + : + : @param comps schema components + : @param nsmap a map of namespace bindings + : @param schemas the schemas to be evaluated + : @param options options controlling the processing + : @return a map with keys 'options' and 'edesc' + :) +declare function ed:foldLeftGetExpandedCompDescs( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as map(xs:string, item()*) { + + (: Sort components in a cache-friendly way :) + let $sortedComps := + for $comp in $comps + let $lname := $comp/local-name(.) + let $compName := $comp/ns:normalizedComponentQName(., $nsmap) + let $kindOrder := + switch($lname) + case 'simpleType' return 1 + case 'element' return 2 + case 'group' return 3 + case 'complexType' return 4 + case 'attribute' return 5 + default return 6 + order by $kindOrder, $compName ! string() ! lower-case(.) + return $comp + + (: Item processing function of fold-left. + : @param accum accumulator + : @param comp a component + : @return the updated accumulator + :) + let $fnGetEdesc := function($accum, $comp) { + let $optionsAct := $accum?options + let $rdesc := $comp/rd:getRequiredCompDescs(., $nsmap, $schemas, $optionsAct) + let $desc := $rdesc?main + let $descsRequired := $rdesc?required + let $expanded := ed:expandCompDesc($desc, $descsRequired, $optionsAct) + ! ns:addNamespaceContext(., $nsmap, $optionsAct) + let $optionsAct2 := dc:storeEdesc($expanded, $optionsAct) + let $accumNew := + map:put($accum, 'options', $optionsAct2) ! + map:put(., 'edesc', ($accum?edesc, $expanded)) + return $accumNew + } + let $accum := map{'options': $options, 'edesc': ()} + let $accumFinal := fold-left($sortedComps, $accum, $fnGetEdesc) + return $accumFinal +}; + +(:~ + : Maps schema components to expanded component descriptors. + : + : @param comps schema components + : @param nsmap namespace prefix bindings + : @param schemas XSD schema elements + : @param options options controlling the processing + : @return component descriptors + :) +declare function ed:getExpandedCompDescs($comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as element()* { + let $cachedAndOthers := + for $comp in $comps + let $edesc := dc:edescForComp($comp, $options) + return ($edesc, $comp)[1] + let $cached := $cachedAndOthers/self::z:* + let $comps := $cachedAndOthers except $cached + return ( + $cached, + if (empty($comps)) then () else + (: + let $_DEBUG := + trace('*** Starting "getExpandedCompDesc"; count comps: '||count($comps)) + :) + (: Process simple types first, in order to get them into the cache :) + let $sortedComps := + for $comp in $comps + let $lname := $comp/local-name(.) + let $compName := $comp/ns:normalizedComponentQName(., $nsmap) + let $kindOrder := + switch($lname) + case 'simpleType' return 1 + case 'element' return 2 + case 'group' return 3 + case 'complexType' return 4 + case 'attribute' return 5 + default return 6 + order by $kindOrder, $compName ! string() ! lower-case(.) + return $comp + + let $edescAndUpdatedOptions := + ed:foldLeftGetExpandedCompDescs($sortedComps, $nsmap, $schemas, $options) + let $edescs := $edescAndUpdatedOptions?edesc + let $optionsUpd := $edescAndUpdatedOptions?options + + let $result := ed:getExpandedCompDescs_addTypeDescriptions($edescs, $optionsUpd) + return $result + ) +}; + +(:~ + : Augments expanded component descriptors by adding to content items + : with a simple type a type descriptions. + : + : @param edescs expanded component descriptors + : @param options options ctonrolling the processing; in particular, + : containing a cache of component descriptors + : @return augmented expanded component descriptors + :) +declare function ed:getExpandedCompDescs_addTypeDescriptions( + $edescs as element()*, + $options as map(xs:string, item()*)) + as element()* { + (: + let $_DEBUG := + let $count := $options?dcache?edesc?simpleType ! map:keys(.) => count() + return trace($count, '*** Add type descriptions: start; #cached simple types: ') + :) + + (: Write dictionaries: + type name -> type description + type ID -> type description + :) + let $typeDescGlobalTypeDict := + map:merge( + for $type in $edescs//@z:type[../@z:typeCategory/starts-with(., 's')] + let $typeName := string($type) + group by $typeName + let $type1 := $type[1] + let $qname := $type1/resolve-QName(., ..) + let $edesc := dc:edescForQName($qname, 'simpleType', $options) + let $typeDesc := + if ($edesc) then sd:edescToTypeDescription($edesc) + else sd:typeNameToTypeDescription($qname, $options?nsmap, $options?schemas?*, $options) + return map:entry($type1, $typeDesc) + ) + let $typeDescLocalTypeDict := + map:merge( + for $typeId in $edescs//@z:typeID[../@z:typeCategory/starts-with(., 's')] + let $typeIdString := string($typeId) + group by $typeIdString + let $typeId1 := $typeId[1] + let $edesc := $typeId1/../z:simpleType + let $typeDesc := $edesc/sd:edescToTypeDescription(.) + return $typeDesc ! map:entry($typeId1, .) + ) + let $edescsUpd := + for $edesc in $edescs + return + if (not($edesc//@z:typeCategory[starts-with(., 's')])) then $edesc + else + + copy $edesc_ := $edesc + modify + for $tcat in $edesc_//*/@z:typeCategory[starts-with(., 's')] + where $tcat and not($tcat/../@z:typeDesc) + let $elem := $tcat/.. + let $type := $elem/@z:type + let $typeDesc := + if ($type) then $typeDescGlobalTypeDict($type) + else + let $typeId := $elem/@z:typeID + return $typeId ! $typeDescLocalTypeDict(.) + where $typeDesc + (: Insert @typeDesc behind @typeCategory :) + let $typeCatAtt := $elem/@z:typeCategory + let $typeDescAtt := attribute z:typeDesc {$typeDesc} + return + if ($typeCatAtt) then + replace node $typeCatAtt with ($typeCatAtt, $typeDescAtt) + else insert node $typeDescAtt into $elem + return $edesc_ + + return $edescsUpd +}; + +(: + : E x p a n s i o n o f a c o m p. d e s c. + : =================================================== + :) +(:~ + : Expands component descriptors. + : + : @param desc component descriptors + : @param descsRequired the component descriptors required for expansion + : @param options options controlling the processing + : @return component descriptors + :) +declare function ed:expandCompDesc($desc as element()*, + $descsRequired as map(xs:string, element()*)?, + $options as map(xs:string, item()*)?) + as element() { + ed:expandCompDescREC($desc, $descsRequired, map{}, $options) +}; + +(:~ + : Recursive helper function of `expandCompDesc`. + : + : @param n a node to be processed during recursive processing + : @param descsRequired the component descriptors required for expansion + : @param visited ? + : @param options options controlling the processing + : @return part of a component descriptor + :) +declare function ed:expandCompDescREC($n as node(), + $descsRequired as map(xs:string, element()*)?, + $visited as map(xs:string, xs:QName*), + $options as map(xs:string, item()*)?) + as node()* { + typeswitch($n) + case document-node() return document{ + $n/node() ! ed:expandCompDescREC(., $descsRequired, $visited, $options)} + case element(z:complexType) return + ed:expandCompDescREC_complexType($n, $descsRequired, $visited, $options) + case element(z:simpleType) return + ed:expandCompDescREC_simpleType($n, $descsRequired, $visited, $options) + case element(z:union) return + ed:expandCompDescREC_union($n, $descsRequired, $visited, $options) + case element(z:list) return + ed:expandCompDescREC_list($n, $descsRequired, $visited, $options) + case element(z:group) return + ed:expandCompDescREC_group($n, $descsRequired, $visited, $options) + case element(z:element) return + ed:expandCompDescREC_element($n, $descsRequired, $visited, $options) + case element() return + ed:expandCompDescREC_any($n, $descsRequired, $visited, $options) + case attribute(z:type) return $n + case attribute() return $n + default return $n +}; + +(:~ + : Helper function of `expandCompDesc`, processing a "complexType" descriptor. + : + : @param n a node to be processed during recursive processing + : @param descsRequired the component descriptors required for expansion + : @param visited ? + : @param options options controlling the processing + : @return part of a component descriptor + :) +declare function ed:expandCompDescREC_complexType + ($n as node(), + $descsRequired as map(xs:string, element()*)?, + $visited as map(xs:string, xs:QName*), + $options as map(xs:string, item()*)?) + as node()* { + let $baseAtt := $n/(z:complexContent, z:simpleContent) + /(z:extension, z:restriction) + /@z:base + return + (: Case 1 - no base type :) + if (not($baseAtt)) then + element {node-name($n)} { + $n/@* ! ed:expandCompDescREC(., $descsRequired, $visited, $options), + $n/node() ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + } + else + + (: Case 2 with base type :) + let $ownContent := ( + $n/@* ! ed:expandCompDescREC(., $descsRequired, $visited, $options), + $baseAtt/../* ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + ) + let $ownContentAtts := $ownContent/self::attribute() + let $ownContentChildren := $ownContent except $ownContentAtts + + (: Base content is an z:baseType element, optionally followed + : by z:extension and/or z:restriction elements + :) + let $baseContent := + let $baseQName := $baseAtt/resolve-QName(., ..) + let $isBaseBuiltin := ns:isQNameBuiltin($baseQName) + (: Base type descriptor :) + let $baseDesc := + if ($isBaseBuiltin) then () else + $descsRequired?type[@z:name/resolve-QName(., ..) eq $baseQName] + (: "Raw" base content - it may miss a base type wrapper :) + let $baseContentRaw := + let $cached := dc:edescForQName($baseQName, 'type', $options) + return if ($cached) then $cached else + $baseDesc ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + return + (: Wrap base content in an z:baseType element; + necessary if this type is immediately derived from the ultimate + base type + :) + if (not($baseContentRaw/z:baseType)) then + { + if ($isBaseBuiltin) then attribute z:name {$baseQName} + else ( + $baseContentRaw/@z:name, + $baseContentRaw/@z:typeCategory, + $baseContentRaw/* + ) + } + (: Raw base content is already a sequence of z:baseType and + z:extension / z:restriction elements :) + else $baseContentRaw/* + return + element {node-name($n)} { + $ownContentAtts, + $baseContent, + element {$baseAtt/../name()} { + $n/@z:name, + $ownContentChildren + } + } +}; + +(:~ + : Helper function of `expandCompDesc`, processing a group element. + : + : @param n a node to be processed during recursive processing + : @param descsRequired the component descriptors required for expansion + : @param options options controlling the processing + : @return part of a component descriptor + :) +declare function ed:expandCompDescREC_group + ($n as node(), + $descsRequired as map(xs:string, element()*)?, + $visited as map(xs:string, xs:QName*), + $options as map(xs:string, item()*)?) + as node()* { + let $ref := $n/@z:ref/resolve-QName(., ..) + let $viaCache := + if (empty($ref)) then () + else + let $cached := dc:edescForQName($ref, 'group', $options) + return if (not($cached)) then () else + + let $refAtt := (attribute z:name {$ref}, attribute z:reference {'yes'}, + attribute z:groupFromCache {'yes'}) + let $atts := $n/(@* except @z:ref) + ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + let $children := $cached/node() + return + element {node-name($n)} {$refAtt, $atts, $children} + return + if ($viaCache) then $viaCache else + ed:expandCompDescREC_any($n, $descsRequired, $visited, $options) +}; + +(:~ + : Helper function of `expandCompDesc`, processing an element element. + : + : @param n a node to be processed during recursive processing + : @param descsRequired the component descriptors required for expansion + : @param options options controlling the processing + : @return part of a component descriptor + :) +declare function ed:expandCompDescREC_element + ($n as node(), + $descsRequired as map(xs:string, element()*)?, + $visited as map(xs:string, xs:QName*), + $options as map(xs:string, item()*)?) + as node()* { + let $ref := $n/@z:ref/resolve-QName(., ..) + let $viaCache := + if (empty($ref)) then () + else + let $cached := dc:edescForQName($ref, 'element', $options) + return if (not($cached)) then () else + + let $refAtt := (attribute z:name {$ref}, attribute z:reference {'yes'}, + attribute z:elementFromCache {'yes'}) + let $atts := $n/(@* except @z:ref) + ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + let $atts2 := $cached/(@* except @z:name) + let $children := $cached/node() + return + element {node-name($n)} {$refAtt, $atts, $atts2, $children} + return + if ($viaCache) then $viaCache else + ed:expandCompDescREC_any($n, $descsRequired, $visited, $options) +}; + +(:~ + : Helper function of `expandCompDesc`, processing unspecific elements. + : + : @param n a node to be processed during recursive processing + : @param descsRequired the component descriptors required for expansion + : @param options options controlling the processing + : @return part of a component descriptor + :) +declare function ed:expandCompDescREC_any + ($n as node(), + $descsRequired as map(xs:string, element()*)?, + $visited as map(xs:string, xs:QName*), + $options as map(xs:string, item()*)?) + as node()* { + + let $name := $n/@z:name/resolve-QName(., ..) + let $newVisited := + if (empty($name)) then $visited else ed:updateVisited($visited, $n, $name) + let $typeID := $n/@z:typeID + return + if (exists($name) and not($typeID)) then + element {node-name($n)} { + $n/@* ! ed:expandCompDescREC(., $descsRequired, $newVisited, $options), + $n/node() ! ed:expandCompDescREC(., $descsRequired, $newVisited, $options) + } + else + + (: Resolve @ref :) + let $ref := $n/@z:ref/resolve-QName(., ..) + let $refCyclic := $ref = $visited(local-name($n)) + let $resolvedRef := + if (empty($ref) or $refCyclic) then () else + $descsRequired(local-name($n))[@z:name/resolve-QName(., ..) eq $ref] + let $refAtt := + if ($resolvedRef) then (attribute z:name {$ref}, attribute z:reference {'yes'}) + else if (exists($ref)) then attribute z:REF-UNRESOLVED {$ref} + else () + let $resolvedRefEdesc := + $resolvedRef/ed:expandCompDescREC(., $descsRequired, $newVisited, $options) + + (: Resolve @typeID :) + let $localTypeEdesc := + if (not($typeID)) then () else + let $localTypeDesc := $descsRequired('localType')[@z:typeID eq $typeID] + return + $localTypeDesc/ed:expandCompDescREC(., $descsRequired, $visited, $options) + + (: Resolve @type :) + let $typeQN := $n/@z:type/resolve-QName(., ..) + let $type := $n/@z:type/string() + let $typeCyclic := $typeQN = $visited(local-name($n)) + let $globalTypeEdesc := + if (empty($type) or not($options?deepResolve) or $typeCyclic) then () else + let $globalTypeDesc := $descsRequired('type')[@z:type eq $type] + return + $globalTypeDesc/ed:expandCompDescREC(., $descsRequired, $visited, $options) + + let $resolvedExpanded := ($resolvedRefEdesc, $localTypeEdesc, $globalTypeEdesc) + (: + let $_DEBUG := + if (count($resolvedExpanded) le 1) then () else + trace(count($resolvedExpanded), concat('Kind=', $n/local-name(), '; Name=', $n/@z:name, '; Ref: ', $n/@z:ref, '; Count: ')) + :) + let $ownAttNames := ($n/@*, $refAtt)/node-name(.) + return + element {node-name($n)} { + (: Own attributes (minOccurs, maxOccurs, ... :) + $refAtt, + $n/@* ! ed:expandCompDescREC(., $descsRequired, $visited, $options), + attribute CYCLIC_REF {local-name($n)||'='||$ref}[$refCyclic], + attribute CYCLIC_TYPE {'@type='||$type}[$typeCyclic], + (: Attributes on referenced component :) + $resolvedExpanded/(@* except @xml:basex)[not(node-name(.) = $ownAttNames)], + (: Own child nodes (annotation, ...) :) + $n/node() ! ed:expandCompDescREC(., $descsRequired, $visited, $options), + (: Child nodes of referenced component :) + $resolvedExpanded/(if (node-name(.) eq $n/node-name(.)) then node() else .) + } +}; + +(:~ + : Helper function of `expandCompDesc`, processing a "simpleType" descriptor. + : + : @param n a node to be processed during recursive processing + : @param descsRequired the component descriptors required for expansion + : @param options options controlling the processing + : @return part of a component descriptor + :) +declare function ed:expandCompDescREC_simpleType + ($n as node(), + $descsRequired as map(xs:string, element()*)?, + $visited as map(xs:string, xs:QName*), + $options as map(xs:string, item()*)?) + as node()* { + let $baseAtt := $n/z:restriction/@z:base + let $restriction := $baseAtt/.. + let $ownContentAtts := + $n/@* ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + let $stypeTree := + (: Case 1 - no base type :) + if (not($baseAtt)) then + element {node-name($n)} { + $ownContentAtts, + $n/*/ed:expandCompDescREC(., $descsRequired, $visited, $options) + } + else + + (: Case 2 with base type :) + let $ownRestriction := + $restriction/* ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + let $baseQName := $baseAtt/resolve-QName(., ..) + let $faceted := + let $baseTypeBuiltin := ns:isQNameBuiltin($baseQName) + let $baseTypeExpanded := + if ($baseTypeBuiltin) then () else + $descsRequired?type[@z:name/resolve-QName(., ..) eq $baseQName] + ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + let $baseType := + if ($baseTypeBuiltin) then + else if ($baseTypeExpanded/z:faceted) then + $baseTypeExpanded/z:faceted/z:baseType + else {$baseTypeExpanded} + + let $restrictions := ( + $baseTypeExpanded/z:faceted/z:restrictions/z:restriction, + {$n/@z:name, $ownRestriction}) + return + { + $baseType, + {$restrictions} + } + return + element {node-name($n)} { + $n/(* except z:restriction) + ! ed:expandCompDescREC(., $descsRequired, $visited, $options), + $faceted + } + let $stypeDescription := sd:edescToTypeDescription($stypeTree) + return + element {node-name($n)} { + $ownContentAtts, + attribute z:typeDesc {$stypeDescription}, + $stypeTree/node() + } +}; + +(:~ + : Helper function of `expandCompDesc`, processing a "union" element. + : + : @param n a node to be processed during recursive processing + : @param descsRequired the component descriptors required for expansion + : @param options options controlling the processing + : @return part of a component descriptor + :) +declare function ed:expandCompDescREC_union + ($n as node(), + $descsRequired as map(xs:string, element()*)?, + $visited as map(xs:string, xs:QName*), + $options as map(xs:string, item()*)?) + as node()* { + let $memberTypes := $n/@z:memberTypes ! tokenize(.) + let $memberTypesReferenced := + for $memberType in $memberTypes + let $memberQName := resolve-QName($memberType, $n) + return + if (ns:isQNameBuiltin($memberQName)) then + + else + let $mtype := $descsRequired?type[@z:name/resolve-QName(., ..) eq $memberQName] + let $mtypeExpanded := + $mtype ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + return $mtypeExpanded + let $memberTypesLiteral := + $n/z:simpleType ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + return + element {node-name($n)} { + ( + $memberTypesReferenced, + $memberTypesLiteral + ) ! {.} + } +}; + +(:~ + : Helper function of `expandCompDesc`, processing a "list" element. + : + : @param n a node to be processed during recursive processing + : @param descsRequired the component descriptors required for expansion + : @param options options controlling the processing + : @return part of a component descriptor + :) +declare function ed:expandCompDescREC_list + ($n as node(), + $descsRequired as map(xs:string, element()*)?, + $visited as map(xs:string, xs:QName*), + $options as map(xs:string, item()*)?) + as node()* { + let $itemTypeReferenced := + let $qname := $n/@z:itemType/resolve-QName(., $n) + where exists($qname) + return + if (ns:isQNameBuiltin($qname)) then + + else + $descsRequired?type[@z:name/resolve-QName(., ..) eq $qname] + ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + ! {.} + let $itemTypeLiteral := + $n/z:simpleType + ! ed:expandCompDescREC(., $descsRequired, $visited, $options) + ! {.} + return + element {node-name($n)} { + ( + $itemTypeReferenced, + $itemTypeLiteral + ) + } +}; + +(:~ + : Updates the map of visited components. Keys are component + : kinds, values are sequences of qualified names. + : + :) +declare function ed:updateVisited($visited as map(xs:string, item()*), + $comp as element(), + $name as xs:QName) + as map(xs:string, item()*) { + let $kind := $comp/local-name(.) + let $updatedNames := ($visited($kind), $name) + return map:put($visited, $kind, $updatedNames) +}; diff --git a/docs/generate_tables/xco-file-util.xqm b/docs/generate_tables/xco-file-util.xqm new file mode 100644 index 000000000..a87820261 --- /dev/null +++ b/docs/generate_tables/xco-file-util.xqm @@ -0,0 +1,222 @@ +(: + : xco-file-util.xqm - utility functions dealing with the file system + :) +module namespace fu="http://www.parsqube.de/ns/xco/file-util"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(: + : + : P u b l i c f u n c t i o n s + : + :) + +(:~ + : Applies a relative path to a context path. A relative context path is + : resolved against the current working directory. The result is an + : absolute path. + : + : @param contextPath the relative path starts at this location + : @param relPath a relative path + : @return a relative path + :) +declare function fu:applyRelPath($contextPath as xs:string, $relPath as xs:string) + as xs:string { + let $cpath := $contextPath ! u:normalizeUri(., ()) + return + if ($relPath = ('', '.')) then $cpath else + fu:applyRelPathREC($cpath, tokenize($relPath, '/')) +}; + +(:~ + : Returns the parent path of a given path. + : + : @param path a path + : @return the parent path + :) +declare function fu:getParentPath($path as xs:string) + as xs:string { + if (not($path)) then '..' + else $path ! u:normalizeUri(., ()) ! replace(., '/[^/]*$', '') +}; + +(:~ + : Returns the parent path of a given path. If the path is a + : relative path, the returned path is also relative. + : + : @param path a path + : @return the parent path + :) +declare function fu:getRelParentPath($path as xs:string) + as xs:string { + if (not($path)) then '..' + else if (not(contains($path, '/'))) then '' + else $path ! replace(., '/[^/]*$', '') +}; + +(:~ + : Returns the relative path leading from a context path to a target location. + : A relative context path or target location is resolved against the current + : working directory. + : + : @param contextPath the relative path starts at this location + : @param targetPath the relative path leads to this location + : @return a relative path + :) +declare function fu:getRelPath($contextPath as xs:string, $targetPath as xs:string) + as xs:string { + let $cpath := $contextPath ! u:normalizeUri(., ()) + let $tpath := $targetPath ! u:normalizeUri(., ()) + return + if ($cpath eq $tpath) then '' else fu:getRelPathREC($cpath, $tpath, ()) +}; + +(:~ + : Applies the relative path leading from a context path to a target location to + : a different context path. + :) +declare function fu:shiftRelPath($contextPath as xs:string, + $targetPath as xs:string, + $newContextPath as xs:string*) + as xs:string { + fu:getRelPath($contextPath, $targetPath) ! fu:applyRelPath($newContextPath, .) +}; + +(:~ + : Returns the file name extension. + :) +declare function fu:getFileExtension($path as xs:string) + as xs:string? { + let $fname := file:name($path) + return $fname ! replace($path, '.*(\.[^.]+$)', '$1')[not(. eq $fname)] +}; + +(:~ + : Removes the file name extension. + :) +declare function fu:removeFileExtension($path as xs:string) + as xs:string { + let $fext := fu:getFileExtension($path) + return substring($path, 1, string-length($path) - string-length($fext)) +}; + +(:~ + : Inserts a label string immediately before the file name extension. + : The label is inserted before the dot. + :) +declare function fu:insertLabelBeforeFileNameExtension($path as xs:string, + $label as xs:string) + as xs:string { + let $fext := fu:getFileExtension($path) + let $suffix := $label||$fext + return fu:removeFileExtension($path)||$suffix +}; + +(:~ + : Replaces the file name extension with a different extension. + :) +declare function fu:changeFileNameExtension($path as xs:string, + $newExtension as xs:string) + as xs:string { + fu:removeFileExtension($path)||'.'||$newExtension +}; + +(:~ + : Copies the standard css file into the report folder, if appropriate. + :) +declare function fu:copyCssFile($options as map(xs:string, item()*)) + as empty-sequence() { + let $odir := $options?odir + return if (not($odir)) then () else + + let $reportType := $options?reportType + return + if ($reportType ne 'contab') then () else + + let $fname := 'asciidoc.css' + let $fpathTarget := $odir||'/'||$fname + return + if (file:exists($fpathTarget)) then () + else + let $sourceDir := static-base-uri() ! fu:getParentPath(.) + let $fpathSource := $sourceDir||'/'||$fname + return file:copy($fpathSource, $fpathTarget) +}; + +(: + : f t r e e c o n s t r u c t o r + : + :) +(:~ + : Maps a sequence of file paths to a tree representation of folders + : and files ( and elements). + : + : @param filePaths a sequence of file paths + : @param context context folder + : @return a tree of and elements + :) +declare function fu:ftree($filePaths as xs:string*, $context as xs:string?) + as element(fo) { + let $paths := $filePaths ! replace(., '^'||$context||'/', '') + => sort((), lower-case#1) + return {fu:ftreeREC($paths)} +}; + +declare function fu:ftreeREC($paths as xs:string*) + as element()* { + let $files := $paths[not(contains(., '/'))] + let $folders := $paths[not(. = $files)] + let $folderTrees := + for $fo in $folders + let $step1 := replace($fo, '/.*', '') + group by $step1 + return + { + $fo ! replace(., '^'||$step1||'/', '') => fu:ftreeREC() + } + return ( + $folderTrees, + $files ! + ) +}; + +(: + : + : P r i v a t e f u n c t i o n s + : + :) + +(:~ + : Recursive helper function of `getRelPath`. + :) +declare %private function fu:getRelPathREC($contextPath as xs:string, + $targetPath as xs:string, + $prefix as xs:string*) + as xs:string { + let $suffix := replace($targetPath, '^'||$contextPath||'/', '') + [. ne $targetPath] + return + if ($suffix) then string-join(($prefix, $suffix), '/') + else + fu:getRelPathREC($contextPath ! fu:getParentPath(.), $targetPath, + ($prefix, '..')) +}; + +(:~ + : Recursive helper function of `applyRelPath`. + :) +declare function fu:applyRelPathREC($contextPath as xs:string, $pathSteps as xs:string*) + as xs:string { + let $step := head($pathSteps) + let $tail := tail($pathSteps) + let $newContextPath := + if ($step eq '..') then $contextPath ! fu:getParentPath(.) + else $contextPath||'/'||$step + return + if (empty($tail)) then $newContextPath + else fu:applyRelPathREC($newContextPath, $tail) +}; + diff --git a/docs/generate_tables/xco-html-util.xqm b/docs/generate_tables/xco-html-util.xqm new file mode 100644 index 000000000..495fa6ffd --- /dev/null +++ b/docs/generate_tables/xco-html-util.xqm @@ -0,0 +1,133 @@ +(: + : xco-html - utility functions supporting the creation of HTML reports + :) +module namespace hu="http://www.parsqube.de/ns/xco/html-util"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; +declare boundary-space preserve; + +(:~ + : Returns the standard colgroup element defining 6 columns. + :) +declare function hu:standardColGroup6() as element(colgroup) { + + + + + + + + +}; + +declare function hu:classTable() as attribute(class) { + 'tableblock frame-all grid-all spread' ! attribute class {.} +}; + +declare function hu:classTd() as attribute(class) { + 'tableblock halign-left valign-top' ! attribute class {.} +}; + +declare function hu:classTd($addClasses as xs:string?) as attribute(class) { + string-join(('tableblock halign-left valign-top', $addClasses), ' ') + ! attribute class {.} +}; + +declare function hu:classP() as attribute(class) { + 'tableblock' ! attribute class {.} +}; + +declare function hu:classP($addClasses as xs:string?) as attribute(class) { + string-join(('tableblock', $addClasses), ' ') ! attribute class {.} +}; + +(: Returns a table text line. The text can be provided as a string + : or as a sequence of nodes and/or strings. + :) +declare function hu:tableTextLine($items as item()*) + as element(tr) { + hu:tableTextLine($items, (), ()) +}; + +(:~ + : Returns a td element containing text rendered as code. + :) +declare function hu:tdWithCode($code as xs:string, + $colspan as xs:integer, + $rowspan as xs:integer) + as element(td) { + { + hu:classTd(), +

{ + hu:classP(), + {$code} + }

+ } +}; + +(:~ + : Returns a td element containing text rendered as code. + :) +declare function hu:tdWithContent( + $content as item()*, + $colspan as xs:integer, + $rowspan as xs:integer) + as element(td) { + hu:tdWithContent($content, $colspan, $rowspan, ()) +}; + +(:~ + : Returns a td element containing text rendered as code. + :) +declare function hu:tdWithContent( + $content as item()*, + $colspan as xs:integer, + $rowspan as xs:integer, + $addClasses as xs:string?) + as element(td) { + { + hu:classTd(), +

{ + hu:classP($addClasses), + $content + }

+ } +}; + +(: Returns a table text line. The text can be provided as a string + : or as a sequence of nodes and/or strings. + :) +declare function hu:tableTextLine($items as item()*, + $addClassesTd as xs:string?, + $addClassesP as xs:string?) + as element(tr) { + let $nodes := $items ! (if (. instance of node()) then . else text {.}) return + { + { + hu:classTd($addClassesTd), +

{ + hu:classP($addClassesP), + $nodes + }

+ } + } +}; + +(:~ + : Returns a multiline HTML representation of a local type label. + :) +declare function hu:getLocalTypeLabelLines($typeLabel as xs:string) + as element()* { + let $id := replace($typeLabel, '.*(\(.*)', '$1') + let $locator := replace($typeLabel, '(.*\]).*', '$1') + let $steps := substring($typeLabel, 1 + string-length($locator)) ! replace(., '\s*\(.*', '') + [string()] + ! replace(., '(\S)#', '$1 #') + return ( + {$locator},
, + $steps ! ({'  '||.},
), + {'  '||$id} + ) +}; + + diff --git a/docs/generate_tables/xco-html.xqm b/docs/generate_tables/xco-html.xqm new file mode 100644 index 000000000..065a83c7e --- /dev/null +++ b/docs/generate_tables/xco-html.xqm @@ -0,0 +1,1056 @@ +(: + : xco-html - functions creating HTML reports + :) +module namespace hl="http://www.parsqube.de/ns/xco/html"; +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; +import module namespace cu="http://www.parsqube.de/ns/xco/custom" + at "xco-custom.xqm"; +import module namespace dg="http://www.parsqube.de/ns/xco/debug" + at "xco-debug.xqm"; +import module namespace dm="http://www.parsqube.de/ns/xco/domain" + at "xco-domain.xqm"; +import module namespace eu="http://www.parsqube.de/ns/xco/edesc-util" + at "xco-edesc-util.xqm"; +import module namespace fu="http://www.parsqube.de/ns/xco/file-util" + at "xco-file-util.xqm"; +import module namespace hu="http://www.parsqube.de/ns/xco/html-util" + at "xco-html-util.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; +declare namespace z="http://www.parsqube.de/ns/xco/structure"; +declare boundary-space preserve; + +(:~ + : Transforms an XML report into an HTML report. + : + : If the report consists of several documents, they are written into files. + : In this case, this function returns only one of the report documents. + : + : @param xmlReport an XML report + : @param options options controlling the processing + : @return the HTML report, or part of the report + :) +declare function hl:htmlReport($reportType as xs:string, + $xmlReport as element()?, + $xmlReportDir as xs:string?, + $options as map(xs:string, item()*)?) + as element()* { + switch($reportType) + case 'contab' return hl:contabReport($xmlReport, $xmlReportDir, $options) + default return error(QName((), 'INVALID_ARG'), + 'Unknown report type: '||$reportType) +}; + +(:~ + : Transforms an edesc report into an contab report. + : + : @param report XML report, report type = "edesc" + : @param options options controlling the processing + : @return the HTML report "contab" + :) +declare function hl:contabReport($report as element()?, + $reportDir as xs:string?, + $options as map(xs:string, item()*)?) + as element()* { + let $domains := $options?domains + let $withEnumDict as xs:boolean := $options?withEnumDict + return + (: No domains defined - create a single report + (Note: reportDir only supported in case of domains) :) + if (not($domains)) then ( + hl:contabReport_domain($report, (), $options), + hl:enumDict_domain($report, (), $options)[$withEnumDict] + ) + + (: Domains have been defined :) + else + let $domainReports := ( + for $domain in $domains/domain + let $_DEBUG := trace($domain/@name, '*** Create report for domain: ') + let $domainReport := + if ($report) then $report/z:domain[@z:id eq $domain/@id] + else + let $inputPath := dm:getInputReportPath('edesc', $reportDir, $domain, $options) + return doc($inputPath)/* + return ( + $domainReport/hl:contabReport_domain(., $domain, $options), + $domainReport/hl:enumDict_domain(., $domain, $options)[$withEnumDict] + ), + hl:contabReportIndex($domains/domain, $options) + ) + return $domainReports[1] +}; + +(:~ + : Transforms an edesc report or report domain into a contab report. + : + : If no domains have been defined, the function creates the complete + : report, otherwise the part corresponding to a single domain. + : + : @param report an edesc report, complete or limited to a domain + : @param domain an element describing the domain + : @param options options controlling the processing + : @return edesc html report, or a part of the report dealing with a domain + :) +declare function hl:contabReport_domain( + $report as element(), + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element() { + let $reportFilePath := dm:getReportPath('edesc-htrml', $domain, $options) + let $head := hl:contabReport_head($reportFilePath, $domain, $options) + let $toc := hl:contabReport_toc($report, $domain, $options) + let $xsdDivs := + for $schema at $schemaNr in $report/z:schema + let $schemaFileName := $schema/base-uri(.) ! replace(., '.+/', '') + let $schemaName := $schemaFileName ! replace(., '(.*)\.[^.]+$', '$1') + let $anno := $schema/z:annotation/z:documentation/string() + let $headline := ($anno, $schemaFileName)[1] + let $stypes := $schema/eu:getEdescReportSimpleTypes(.) + let $stypesTable := eu:stypesTable($stypes, $domain, $options)[$stypes] + let $tables := + for $comp at $cnr in ( + $schema/z:components/*, + $schema/z:components/*//z:complexType[@z:typeID] ! u:copyNode(.) + ) + let $compNr := + let $shift := if ($stypes) then 1 else 0 + return $cnr + $shift + return + typeswitch($comp) + case element(z:complexType) | + element(z:group) | + element(z:element) return + hl:contabReport_complexComp($comp, $compNr, $schemaNr, $domain, $options) + case element(z:simpleType) return () + case element(z:attributeGroup) return () + case element(z:attribute) return () + default return error('Unexpected component, elem name: '||name($comp)) + return +
{ +

{$schemaNr}. {$headline}

, + + if (not($stypes)) then () else + hl:contabReport_stypes($schemaName, $schemaNr, $stypesTable), + $tables + }
+ + let $title := ($domain/processing/title/

{node()}

,

API Content

)[1] + let $htmlReport := + { + $head, + { + , +
{ + $xsdDivs + }
+ } + } + ! u:prettyNode(.) + let $_WRITE := + let $reportPath := dm:getReportPath('contab', $domain, $options) + where ($reportPath) + return u:writeXmlDoc($reportPath, $htmlReport) + return $htmlReport +}; + +(:~ + : Returns a
element containing a TOC. + :) +declare function hl:contabReport_toc( + $report as element(), + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element() { + let $custom := $options?custom + let $xsdDict := $options?schemas return + +
+
Table of Contents
+
    { + for $schema at $snr in $report/z:schema + let $baseUri := $schema/base-uri(.) + let $xsd := $options?schemas($baseUri) + let $schemaFileName := $baseUri ! file:name(.) + let $schemaName := $schemaFileName ! replace(., '(.*)\.[^.]+$', '$1') + let $xsdTitle := cu:xsdTitle($schema/@filePath ! $xsdDict(.), + 'contab', $domain/@id, $options?custom) + let $stypes := $schema/z:components/z:simpleType + let $shift := if ($stypes) then 1 else 0 + return +
  • + {$snr}. {$xsdTitle} +
      { +
    • + {$snr}.1. Simple type definitions +
    • [$stypes], + + for $comp at $cnr in $schema/z:components/* + [self::z:element, self::z:complexType, self::z:group] + let $compNr := $shift + $cnr + let $compKind := $comp/local-name(.) + let $name := $comp/@z:name/string() + let $dispName := cu:customComponentName( + $name, $compKind, 'main', 'contab', $domain/@id, $custom) + let $ttp := ( + typeswitch($comp) + case element(z:element) return 'The toplevel element~~element.' + case element(z:complexType) return 'The complexType~~type.' + case element(z:group) return 'The ~group~group.' + default return error() + ) => tokenize('~') + let $txt1 := $ttp[1] + let $txt2 := $ttp[2] + let $idPrefix := $ttp[3] + return +
    • + {$snr}.{$compNr} {$txt1} {$dispName}{$txt2} + +
    • + }
    +
  • + }
+
+}; + +(:~ + : Returns the head part of a contab report page. + : + : @param report XML report + : @param reportPath the file path where this document will be written + : @param domain the current domain + : @param options options controlling the processing + : @return component descriptors + :) +declare function hl:contabReport_head( + $reportPath as xs:string, + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element() { + let $title := ($domain/processing/title/string(), 'API types')[1] + let $odir := $options?odir + let $cssFilePath := $odir||'/asciidoc.css' + let $cssRelFilePath := fu:getRelPath($reportPath ! fu:getParentPath(.), $cssFilePath) + return + + + {$title} + + + + + , + + + +}; + +declare function hl:contabReport_stypes($schemaName, + $schemaNr, + $stypesTable) + as element(div) { +
{ +

{$schemaNr}.1. Simple type definitions

, +
{ + { + + + + + , + { + for $row in $stypesTable/* + let $nameHtml := + let $raw := $row/name + return + if ($raw/contains(., '#')) then + hu:getLocalTypeLabelLines($raw) + else + {$raw/node()} + let $enums := $row/description/enum + let $anno := ($row/anno[string()]/string(), '-')[1] + return if (not($enums)) then + + (: Case 1 - not an enum gtype :) + $row/ + { + name/ + , + description/ + , + anno/ + + } + + (: Case 2 - enum gtype :) + else ( + $row/ + { + name/ + , + anno/ + + }, + + { + + }) + + } + }
{ + hu:classTd(), +

{ + hu:classP(), $nameHtml + }

+ }
{ + hu:classTd(), +

{hu:classP(), node()}

+ }
{ + hu:classTd(), +

{hu:classP('anno-text'), $anno}

+ }
{ + hu:classTd(), +

{ + hu:classP(), + if (not(@linkName/string())) then + $nameHtml + else + {$nameHtml} + }

+ }
{ + hu:classTd(), +

{hu:classP('anno-text'), $anno}

+ }
{ + { + hu:classTable(), + + + + , + + { + $enums/ + { + , + + } + } + }
{ + hu:classTd(), +

{hu:classP(), @value/string(.)}

+ }
{ + hu:classTd(), +

{hu:classP('anno-text'), + (@anno/string()[string()], '-')[1] + }

+ }
+ }
+ + }
+ }
+}; + +(:~ + : Contributes to an contab report the description of a complex + : component. A complex component can be an element declaration, + : a type definition or a group definitions. + : + : @param comp extended descriptor of a schema component + : @param compNr an ordinal number defining the position of the + : component within a sequence of components + : @param schemaNr an ordinal number defining the position of the + : containing schema withion a sequence of schemas + : @param domain an optional definition of the containing domain + : @return an HTML div element + :) +declare function hl:contabReport_complexComp( + $comp as element(), + $compNr as xs:integer, + $schemaNr as xs:integer, + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element()* { + let $custom := $options?custom + let $contentTable := eu:contentTable($comp, $domain, $options) + let $compKind := $comp/local-name(.) + let $kindName := + switch($compKind) + case 'complexType' return 'complex type' + case 'group' return 'group' + case 'element' return 'toplevel element' + default return error() + let $idPrefix := + switch($compKind) + case 'complexType' return 'type' + default return $comp/local-name(.) + let $name := $contentTable/@name + let $kind := $contentTable/@kind + let $typeId := $contentTable/@typeID + let $typeLabel := $contentTable/@typeLabel + let $compDisplayName := + if ($typeLabel) then $typeLabel/string() + else + cu:customComponentName( + $name, $compKind, 'main', 'contab', $domain/@id, $custom) + let $lexName := $contentTable/@name + let $divId := + if (not($comp/self::z:complexType/@z:typeID)) then $idPrefix||'.'||$lexName + else 'local-type.'||$comp/@z:typeID + return ( +
{ +

{$schemaNr}.{$compNr}. The {$kindName} {$compDisplayName}

, +
{ + if ($contentTable/@variant eq 'typeName') then + hl:contentHtmlTable_variant_typeName($contentTable) + else + hl:contentHtmlTable_std($contentTable, $comp, $domain, $options) + }
+ }
+ ) +}; + +(:~ + : Returns a table element representing the content of a complex component. + : + : @param contentTable a content table containing the essential data + : @param comp a component descriptor + : @param domain the domain containing the component + : @param options options controlling the processing + : @return a table element + :) +declare function hl:contentHtmlTable_std($contentTable as element(), + $comp as element(), + $domain as element(domain)?, + $options as map(xs:string, item()*)) + as element(table) { + let $custom := $options?custom + let $compKind := $contentTable/@kind/string() + let $compAnno := $contentTable/(anno[string()]/string(), '-')[1] + let $name := $contentTable/@name + let $baseName := $contentTable/@baseName + let $baseLinkName := $contentTable/@baseLinkName + let $compositor := + $comp/*/descendant::*[self::z:sequence, self::z:choice, self::z:choice][1] + /local-name(.) + ! replace(., '.*:', '') + let $typeId := $contentTable/@typeID + let $typeLabel := $contentTable/@typeLabel + let $compDisplayName := + if ($typeLabel) then $typeLabel/hu:getLocalTypeLabelLines(.) (: u:getDescriptorLocalTypeLabelDivs(.) :) + else + cu:customComponentName( + $name, $compKind, 'main', 'contab', $domain/@id, $custom) + ! {.} + let $baseDisplayName := + $baseName ! cu:customComponentName( + ., $compKind, 'sub', 'contab', $domain/@id, $custom) + + let $baseTypeContent := $contentTable/rows/baseTypeContent + let $typeContent := $contentTable/rows/typeContent + let $withBaseType := exists($baseTypeContent) + let $baseTypeHasItems := exists($baseTypeContent//row/name) + let $firstRowOwnContent := $typeContent/descendant::row[1][$withBaseType] + let $typeIsRestriction := $typeContent/@isRestriction eq 'yes' + return + + { + hu:classTable(), + hu:standardColGroup6(), + { + (: Headline providing component name, base type name or link, component annotation + =============================================================================== :) + { + (: Component display name :) + hu:tdWithContent($compDisplayName, 4, 1) + , + (: Base type name or link :) + let $content := + if (not($baseName)) then () + else if (not($baseLinkName)) then {$baseDisplayName} + else + {$baseDisplayName} + return hu:tdWithContent($content, 1, 1), + + (: Component annotation :) + hu:tdWithContent($compAnno, 1, 1, 'anno-text') + }, + hu:tableTextLine( + ('The element content starts with ', items inherited, ' from the base type:'), + 'announceBase', ())[$withBaseType][$baseTypeHasItems] + , + (: + hu:tableTextLine( + ('The element contains a ', {$compositor}, ' of the following elements:')) + , + :) + for $row in $contentTable//row + let $typeCategory := $row/@typeCategory + let $isComplex := $typeCategory eq 'cc' + let $displayName := $row/name/( + if (not($custom)) then . else + cu:customComponentName( + ., 'element', 'sub', 'contab', $domain/@id, $custom)) + let $isMandatory := not($row/occ/starts-with(., '0')) + let $fnItemName := function($name, $linkName, $isMandatory) { + let $name := + if ($linkName) then ( + text{'→‍'}, + { + $displayName}) + else text{$displayName} + return + if ($isMandatory) then {$name} + else {$name} + (: + if ($isMandatory) + then {$name} + else {$name} + :) + } + let $occValue := '-'[$row/branch/string()]||$row/occ + let $occTitle := + let $min := $row/occ/substring-before(., ':') + let $max := $row/occ/substring-after(., ':') + let $piece1 := if ($min eq '0') then 'optional' else 'mandatory' + let $piece2 := + if ($max eq '1') then 'single' + else if ($max ne '*') then 'at most '||$max + else if ($piece1 eq 'optional') then 'multiple' + else 'at least one' + let $piece3 := if ($row/branch/string()) then 'part of a choice' else () + return string-join(($piece1, $piece2, $piece3), ', ') +(: +mandatory, at least one +mandatory, single +optional, multiple +optional, single +mandatory, at least one, part of a choice +mandatory, single, part of a choice +optional, single, part of a choice +:) + let $typeCatMarker := + switch($typeCategory) + case 'cc' return '+' + case 'cs' return '>' + default return () + let $startOwnContent := $row is $firstRowOwnContent + let $startOwnContentMsg := + if (not($startOwnContent)) then () + else if ($typeIsRestriction) then ( + 'Base type content is ', restricted, ', resulting in the following ', own content, ':') + else ( + 'Inherited content is followed by ', own content, ':') + + let $startChoiceItems := $row/@startChoice/tokenize(., ';\s*') + return ( + hu:tableTextLine($startOwnContentMsg, 'announceBase', ())[$startOwnContent] + , + if (empty($startChoiceItems)) then () else + for $startChoiceItem in $startChoiceItems + let $items := tokenize($startChoiceItem, ',\s*') + let $contextbranch := $items[starts-with(., 'contextbranch')] ! substring-after(., '=') + let $elems := $items[starts-with(., 'elems')] ! substring-after(., '=') + let $seqs := $items[starts-with(., 'seqs')] ! substring-after(., '=') + let $startText := + if (not($contextbranch)) then 'The ' + else + 'In case of choice '''||$contextbranch||''', the ' + let $alternatives := string-join(( + $elems ! ('elements ('||$elems||')'), + $seqs ! ('element sequences ('||$seqs||')') + ), ' or ') + return + hu:tableTextLine( + ($startText, 'element contains ', one, + ' of the following '||$alternatives)) + , + { + $row/group/ + , + $row/branch/ + , + $row/name/ + , + $row/occ/ + , + $row/type/ + , + $row/anno/ + + } + ) + } + }
{ + hu:classTd(), + let $displayName := + if (not($custom)) then . else + cu:customComponentName( + ., 'group', 'sub', 'contab', $domain/@id, $custom) + return + {$displayName} + }{ + hu:classTd(), +

{ + hu:classP(), + {string()} + }

+ }
{ + hu:classTd(), +

{ + hu:classP(), + $fnItemName($displayName, @linkName, $isMandatory) + (: + if (@linkName) then $fnItemName(( + text{'→‍'}, {$displayName}), + $isMandatory) + else + $fnItemName($displayName, $isMandatory) + :) + }

+ }
{ + hu:classTd(), +

{ + hu:classP(), + if ($isMandatory) then + {$occValue} + else + {$occValue} + }

+ }
{ + hu:classTd(), + let $displayName := + if (not($custom)) then . else + cu:customComponentName( + ., 'complexType', 'sub', 'contab', $domain/@id, $custom) + return +

{ + hu:classP(), + { + if (@builtin[string()]/xs:boolean(.)) then text {string()} + else ( + $typeCatMarker, + {$displayName} + ) + } + }

+ }
{ + hu:classTd(), +

{hu:classP('darkbrown'), string()}

+ }
+}; + +(:~ + : Returns a table element representing the content of an + : element component with a type attribute. + : + : @param contentTable a content table containing the essential data + : @param comp a component descriptor + : @param domain the domain containing the component + : @param options options controlling the processing + : @return a table element + :) +declare function hl:contentHtmlTable_variant_typeName($contentTable as element()) + as element(table) { + { + hu:classTable(), + hu:standardColGroup6(), + { + $contentTable/descendant::row[1]/ + { + name/ + , + type/ + , + anno/ + + } + } + }
{ + hu:classTd(), +

{ + hu:classP(), + {string()} + }

+ }
{ + hu:classTd(), +

{ + hu:classP(), + if (not(@linkName/string())) then + {string()} + else + +{string()}, + @substitutionGroup[string()] + ! ('(', ↔ {string()}, ')') + }

+ }
{ + hu:classTd(), +

{ + hu:classP(), + string() + }

+ }
+}; + +(: + : I n d e x + : ========= + :) + + (:~ + : Writes an HTML index page, which is an entry point for + : the XSD Content Report. + :) +declare function hl:contabReportIndex( + $domains as element()*, + $options as map(xs:string, item()*)) + as element(html) { + let $reportType := $options?reportType + let $odir := $options?odir + let $pageDir := $odir||'/'||$reportType + let $fileName := $reportType||'-index.html' + let $filePath := $pageDir||'/'||$fileName + let $title :=

{cu:systemTitleNodes('contab', $options?custom, $options)}

+ let $head := hl:contabReport_head($filePath, (), $options) + let $toc := hl:contabReportIndex_toc($filePath, $domains, $options) + let $htmlReport := + { + $head, + { + , +
{ + }
+ } + } + ! u:prettyNode(.) + + let $_WRITE := u:writeXmlDoc($filePath, $htmlReport) + + return $htmlReport +}; + +(:~ + : Constructs the table of content displayed by the + : XSD Content Report index page. + :) +declare function hl:contabReportIndex_toc( + $filePath as xs:string, + $domains as element()*, + $options as map(xs:string, item()*)?) + as element() { + let $dirPath := $filePath ! fu:getParentPath(.) + let $reportType := $options?reportType + + let $domainDict := map:merge( + for $domain in $domains + let $filePath := dm:getReportPath('contab', $domain, $options) + let $relPath := fu:getRelPath($dirPath, $filePath) + let $fileName := $relPath ! file:name(.) + let $title := $domain/processing/title/string() + let $enumPath := + dm:getReportPartPath('contab', 'enum-dict', $domain, $options)[file:exists(.)] + let $enumRelPath := $enumPath ! fu:getRelPath($dirPath, .) + let $enumFileName := $enumRelPath ! file:name(.) + let $countEnumTypes := + $enumPath ! doc(.)//div[@class eq 'enum-type-definition'] => count() + return ( + map:entry($relPath, map{ + 'filePath': $filePath, + 'fileName': $fileName, + 'relPath': $relPath, + 'title': $title + }), + map:entry($enumRelPath, map{ + 'filePath': $enumPath, + 'fileName': $enumFileName, + 'relPath': $enumRelPath, + 'title': $title||' (enumerations)', + 'countEnumTypes': $countEnumTypes + })[$enumPath] + )) + let $relPaths := map:keys($domainDict) => sort() + let $ftree := fu:ftree($relPaths, $dirPath) + let $linkTree := hl:contabReportIndex_tocTree($ftree, $domainDict, $options) + let $title := 'Table of Contents' + let $subtitle := + let $reportLabel := + if ($options?domainType eq 'xsd') then 'XSD reports' else 'reports' + return count($domains)||' '||$reportLabel + let $_DEBUG := dg:WRITE_FILE($ftree, 'FTREE.XML', 'ftree', 'yes', $options) + return + +
+
+

{$title}

+

{$subtitle}

+
+
    { + $linkTree + }
+
+}; + +(:~ + : Maps a folder tree representation of report files to + : a sequence of list item elements representing folders + : and files + : + : @param ftree folder tree + : @param domainDict maps paths to domain information + : @param options options controlling the processing + :) +declare function hl:contabReportIndex_tocTree( + $ftree as element(fo), + $domainDict as map(xs:string, item()*), + $options as map(xs:string, item()*)?) + as element(li)* { + hl:contabReportIndex_tocTreeREC($ftree, $domainDict, $options) +}; + +declare function hl:contabReportIndex_tocTreeREC( + $n as node(), + $domainDict as map(xs:string, item()*), + $options as map(xs:string, item()*)?) + as element()* { + typeswitch($n) + case element(fo) return + let $level := count($n/ancestor::fo) + let $prefix := (for $i in 1 to $level return '>> ') => string-join('') + return ( +
  • { + {$prefix}, + {$n/@name/string()} + }
  • , + $n/* ! hl:contabReportIndex_tocTreeREC(., $domainDict, $options) + ) + case element(fi) return + let $href := $n/ancestor-or-self::*/@name => string-join('/') + let $isEnumDict := contains($href, 'enum-dict') + return if ($isEnumDict and not($options?withEnumDict)) then () else + + let $path := $n/ancestor-or-self::*/@name => string-join('/') + let $level := count($n/ancestor::fo) + let $prefix := (for $i in 1 to $level return '. ') => string-join('') + let $dinfo := $domainDict($path) + let $href := $dinfo?relPath + let $title := $dinfo?fileName|| + ($dinfo?countEnumTypes[string()] ! (' ('||.||')')) + let $titleClass := attribute class {'enum-dict'} + [contains($href, 'enum-dict')] + return +
  • { + {$prefix}, + {$titleClass, $title} + }
  • + default return () +}; + +(: + : E n u m d i c t + : ================== + :) + +(:~ + : Transforms an edesc report or report domain into an contab report. + : + : If no domains have been defined, the function creates the complete + : report, otherwise the part corresponding to a single domain. + : + : @param report an edesc report, complete or limited to a domain + : @param domain an element describing the domain + : @param options options controlling the processing + : @return edesc html report, or a part of the report dealing with a domain + :) +declare function hl:enumDict_domain( + $report as element(), + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element()? { + if (not($report//z:enumeration)) then () else + + let $_DEBUG := trace($options?withEnumDict, '_______________________WITH_ENUM_DICT: ') + + let $reportFilePath := dm:getReportPartPath('contab', 'enum-dict', $domain, $options) + let $_DEBUG := trace($reportFilePath, '_REPORT_FILE_PATH: ') + let $head := hl:contabReport_head($reportFilePath, $domain, $options) + let $enumTypes := eu:getEdescReportEnumTypes($report) + let $toc := hl:contabReport_enumDict_toc($enumTypes, $domain, $options) + let $enumDivs := + for $stype in $enumTypes + let $lname := $stype/ + (@z:name/replace(., '.+:', ''), u:getLocalTypeLabel(., $options?nsmap, $options))[1] + let $globalOrLocal := if ($stype/@z:typeID) then 2 else 1 + order by $globalOrLocal, $lname + count $pos + return hl:enumDict_stype($stype, $pos, $domain, $options) + let $title := ($domain/processing/titleEnumDict/

    {node()}

    , +

    {'Enumeration Dictionary ('||$domain/@name||')'}

    )[1] + let $htmlReport := + { + $head, + { + , +
    { + $enumDivs + }
    + } + } + ! u:prettyNode(.) + + let $_WRITE := + let $reportPath := dm:getReportPartPath('contab', 'enum-dict', $domain, $options) + where ($reportPath) + return u:writeXmlDoc($reportPath, $htmlReport) + + return $htmlReport +}; + +(:~ + : Returns a
    element containing a TOC. + :) +declare function hl:contabReport_enumDict_toc( + $enumTypes as element()*, + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element() { + let $custom := $options?custom + let $xsdDict := $options?schemas return + +
    +
    Table of Contents - Enumeration types
    +
      { + for $type at $tnr in $enumTypes + let $typeName := $type/@z:name/string() + let $typeId := $type/@z:typeID/string() + let $typeLabel := $type/u:getDescriptorLocalTypeLabel(.) + let $displayName := ($typeName, $typeLabel)[1] + let $lname := (replace($typeName, '.+:', ''), $typeLabel)[1] + let $anno := + let $raw := $type/z:annotation/z:documentation/normalize-space(.) + ! replace(., '(.*?\.).*', '$1') + return + if ($raw) then $raw + else if ($typeId) then '(Local type without documentation)' + else '(Without documentation)' + let $href := + if ($typeName) then '#enum.'||$typeName + else '#local-enum.'||$typeId + let $globalOrLocal := if ($typeId) then 2 else 1 + order by $globalOrLocal, $lname + count $tnr + return +
    • { + {$tnr}. {$displayName}, + text{' - '}, + {$anno} + }
    • + }
    +
    +}; + +declare function hl:enumDict_stype( + $stype as element(z:simpleType), + $typePos as xs:integer, + $domain as element(domain)?, + $options as map(xs:string, item()*)?) + as element() { + let $custom := $options?custom + let $typeName := $stype/@z:name + let $typeId := $stype/@z:typeID + let $typeLabel := $stype/u:getDescriptorLocalTypeLabel(.) + let $divId := if ($typeName) then 'enum.'||$typeName else 'local-enum.'||$typeId + let $anno := $stype/z:annotation/z:documentation/normalize-space(.) + let $compDisplayName := + if ($typeLabel) then $typeLabel + else + cu:customComponentName( + $typeName, 'simpleType', 'main', 'contab', $domain/@id, $custom) + return +
    { +

    {$typePos}. {$compDisplayName}

    , +
    { + + + + + + { + + + , + for $enum in $stype//z:enumeration + let $value := $enum/@z:value/string() + let $anno := + ($enum/z:annotation/z:documentation/normalize-space(.), '-')[1] + return + { + , + + } + } +
    { + hu:classTd(), +

    {hu:classP(), {$anno}}

    + }
    +

    + {$value} +

    +
    +

    {$anno}

    +
    + }
    + }
    +}; + diff --git a/docs/generate_tables/xco-link.xqm b/docs/generate_tables/xco-link.xqm new file mode 100644 index 000000000..5789cf089 --- /dev/null +++ b/docs/generate_tables/xco-link.xqm @@ -0,0 +1,145 @@ +(: + : Functions calculating link addresses. + :) +module namespace ln="http://www.parsqube.de/ns/xco/link"; + +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; + +import module namespace dg="http://www.parsqube.de/ns/xco/debug" + at "xco-debug.xqm"; + +import module namespace dm="http://www.parsqube.de/ns/xco/domain" + at "xco-domain.xqm"; + +import module namespace fu="http://www.parsqube.de/ns/xco/file-util" + at "xco-file-util.xqm"; + +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; + +import module namespace sd="http://www.parsqube.de/ns/xco/simple-type-description" + at "xco-stype-description.xqm"; + +import module namespace sf="http://www.parsqube.de/ns/xco/string-filter" + at "xco-sfilter.xqm"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Returns the link address for a type definition. + : + : @param domain the optional domain containing the link source + : @param targetName qualified name of the target + : @param typeDesc type description of the target + : @return link address + :) +declare function ln:getTypeLinkRef($domain as element()?, + $targetName as xs:QName, + $typeDesc as xs:string?, + $options as map(xs:string, item()*)) + as xs:string? { + if (ns:isQNameBuiltin($targetName)) then () + else if (not($typeDesc ! sd:isTypeDescriptionEnumDesc(.)) + or not($options?withEnumDict)) then + ln:getLinkRef($domain, 'type', $targetName, $options) + else + + let $hrefFragment := '#enum.'||$targetName + return + if (not($domain)) then + let $sourcePath := dm:getReportPath('contab', (), $options) + let $targetPath := dm:getReportPartPath('contab', 'enum-dict', (), $options) + let $relPath := fu:getRelPath($sourcePath, $targetPath) + return $relPath||$hrefFragment + else + + let $fnFindComp := $dm:findComps('type') + let $ns := namespace-uri-from-QName($targetName) + let $lname := local-name-from-QName($targetName) + return + let $sourceDomainPath := dm:getReportPath('contab', $domain, $options) + let $sourceDomainParentPath := $sourceDomainPath ! fu:getParentPath(.) + let $targetDomain := $domain/../*[$fnFindComp(., $ns, $lname)][1] + let $targetDomain := ($targetDomain, $domain)[1] + (: A broken link, unless the targetDomain has been found :) + let $targetDomainPath := dm:getReportPartPath('contab', 'enum-dict', $targetDomain, $options) + let $relTargetDomainPath := fu:getRelPath($sourceDomainParentPath, $targetDomainPath) + return $relTargetDomainPath||$hrefFragment +}; + +(:~ + : Returns the href string to be used when referencing a + : schema component from a schema in a given domain. + : + : @param domain the domain to which the link source belongs + : @param targetKind the kind of component to be referenced + : (element/attribute/type/group/attributeGroup) + : @return the string to be used as @href value + :) +declare function ln:getLinkRef($domain as element()?, + $targetKind as xs:string, + $targetName as xs:QName, + $options as map(xs:string, item()*)) + as xs:string? { + let $ns := namespace-uri-from-QName($targetName) + return if ($ns eq $co:URI_XSD) then () else + + let $hrefFragment := '#'||$targetKind||'.'||$targetName + return if (not($domain)) then $hrefFragment else + + let $sourceDomainPath := dm:getReportPath('contab', $domain, $options) + let $sourceDomainParentPath := $sourceDomainPath ! fu:getParentPath(.) + let $fnFindComp := $dm:findComps($targetKind) + let $lname := local-name-from-QName($targetName) + let $inSameDomain := $domain/$fnFindComp(., $ns, $lname) + return + if ($inSameDomain) then $hrefFragment else + + let $targetDomain := $domain/../*[$fnFindComp(., $ns, $lname)][1] + let $targetDomain := ($targetDomain, $domain)[1] + (: A broken link, unless the targetDomain has been found :) + let $targetDomainPath := dm:getReportPath('contab', $targetDomain, $options) + let $relTargetDomainPath := fu:getRelPath($sourceDomainParentPath, $targetDomainPath) + return $relTargetDomainPath||$hrefFragment +}; + +(:~ + : Returns the href string to be used when referencing a + : local type definition. + : + : @param typeId the type Id + : @return the string to be used as @href value + :) +declare function ln:getLocalTypeLinkRef( + $domain as element()?, + $typeId as xs:string, + $tdesc as xs:string?, + $options as map(xs:string, item()*)) + as xs:string? { + if (not($tdesc ! sd:isTypeDescriptionEnumDesc(.))) then + '#local-type.'||$typeId + else + ln:getLocalEnumTypeLinkRef($domain, $typeId, $options) +}; + +(:~ + : Returns the href string to be used when referencing a + : local enum type definition. + : Important - if domains are used, the link source is assumed + : in the same domain as the link target. + : + : @param typeId the type Id + : @return the string to be used as @href value + :) +declare function ln:getLocalEnumTypeLinkRef( + $domain as element()?, + $typeId as xs:string, + $options as map(xs:string, item()*)) + as xs:string? { + let $domainFile := $domain/dm:getReportPartPath('contab', 'enum-dict', ., $options) + return $domainFile||'#local-enum.'||$typeId +}; diff --git a/docs/generate_tables/xco-namespace.xqm b/docs/generate_tables/xco-namespace.xqm new file mode 100644 index 000000000..c79465e9e --- /dev/null +++ b/docs/generate_tables/xco-namespace.xqm @@ -0,0 +1,203 @@ +(: + : Namespace-related tool functions + :) +module namespace ns="http://www.parsqube.de/ns/xco/namespace"; + +import module namespace co="http://www.parsqube.de/ns/xco/constants" +at "xco-constants.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Returns the qualified name of a top-level component. + : + : @param comp a schema component + : @return the QName of the component + :) +declare function ns:componentQName($comp as element()) + as xs:QName { + $comp/QName(ancestor::xs:schema/@targetNamespace, @name) +}; + +(:~ + : Returns the normalized QName of an XSD component. The comonent + : is expected to be a child element of the schema element, with + : a @name attribute. + : + : @param comp a schema component + : @param nsmap a map representing the binding of namespace prefixes + : @return the normalized QName of the component + :) +declare function ns:normalizedComponentQName( + $comp as element(), + $nsmap as element(z:nsMap)?) + as xs:QName { + ns:componentQName($comp) ! ns:normalizeQName(., $nsmap) +}; + + + +(:~ + : Normalizes a QName in accordance with a map of namespace bindings. + : + : @param qname the QName to be normalized + : @param nsmap a map representing the binding of namespace prefixes + : @return the normalized QName + :) +declare function ns:normalizeQName( + $qname as xs:QName, + $nsmap as element(z:nsMap)?) + as xs:QName { + + if (empty($nsmap)) then $qname + else + let $uri := namespace-uri-from-QName($qname)[string()] + (: if no namespace, the URI must be empty sequence :) + return + if (empty($uri)) then $qname else + + let $prefix := $nsmap/z:ns[@uri eq $uri]/@prefix + return + if (empty($prefix)) then $qname else + let $lexName := string-join(($prefix, local-name-from-QName($qname)), ':') + return QName($uri, $lexName) +}; + +(:~ + : Resolves a normalized lexical name to a QName. + : + : @param name a normalized lexical name + : @param nsmap a map representing the binding of namespace prefixes + : @return a QName + :) +declare function ns:resolveNormalizedLexName( + $name as xs:string, + $nsmap as element(z:nsMap)?) + as xs:QName { + if (not(contains($name, ':'))) then QName((), $name) else + + let $prefix := replace($name, '^(.+):.*', '$1') + let $uri := $nsmap/z:ns[@prefix eq $prefix]/@uri + return QName($uri, $name) +}; + +(:~ + : Determines whether a given QName belongs to the XSD namespace. + : + : @param qname the QName to be normalized + : @return true or false, dependent on whether the name is in the XSD namespace + :) +declare function ns:isQNameBuiltin($qname as xs:QName?) + as xs:boolean? { + $qname ! (namespace-uri-from-QName(.) eq $co:URI_XSD) +}; + +(:~ + : Creates a map associating all target namespaces with normalized prefixes. + : A normalized prefix is either customized prefix or a computed prefix. + : Customized namespace bindings are defined by config data: + : config/namespaces/namespace/(@prefix, @uri) + : + : The map contains additional entries, associating the prefix 'z' with the + : namespace of xco structures, 'xml' and 'xs' with the official xml and XSD + : namespaces. + : + : @schemas the schemas to be evaluated + : @return a map containing prefix/uri pairs + :) +declare function ns:getTnsPrefixMap($schemas as element(xs:schema)*, + $custom as element()?) + as element(z:nsMap) { + let $customBindings := $custom/namespaces/namespace + let $tnss := + for $t in distinct-values($schemas/@targetNamespace) + order by lower-case($t) + return $t + let $tnssCustom := $tnss[. = $customBindings/@uri] + return + { + (: Customized bindings :) + for $tns in $tnssCustom + return $customBindings[@uri eq $tns]/, + (: Computed bindings :) + let $prefixTnsPairs := $tnss[not(. = $tnssCustom)] => ns:_getPrefixTnsPairs() + for $pair in $prefixTnsPairs + let $prefix := substring-before($pair, ':') + let $tns := substring-after($pair, ':') + where not($tns eq $co:URI_XSD) + return + { + attribute prefix {$prefix}, + attribute uri {$tns} + }, + (: Standard bindings :) + , + , + + } +}; + +(:~ + : Returns for a sequence of namespace URIs the normalized prefixes. For each + : namespace a colon-separated concatenation of prefix and namespace URI is + : returned. Normalized prefixes are the lower case letters corresponding to + : the position of the namespace URI within the list of namespace URIs. If + : the position is gt 25, the letters are reused and a suffix is appended + : which indicates the number of the current letter cycle (2, 3, ...). The + : prefixses therefore are: + : 'a', 'b', 'c', ..., 'x', 'y', 'a2', 'b2', ..... + : + : @tnss the target namespaces + : @return the prefix/tns pairs + :) +declare function ns:_getPrefixTnsPairs($tnss as xs:string*) + as xs:string* { + for $tns at $pos in $tnss + let $seriesNr := ($pos - 1) idiv 25 + let $postfix := if (not($seriesNr)) then () else $seriesNr + 1 + let $p := 1 + ($pos - 1) mod 25 + let $char := substring('abcdefghijklmnopqrstuvwxy', $p, 1) + let $prefix := concat($char, $postfix) + where not($tns eq 'http://www.w3.org/XML/1998/namespace') + return concat($prefix, ':', $tns) +}; + +(:~ + : Adds to an element the namespace bindings described by a namespace map. + : + : @param elem the element to be modified + : @param nsmap a namespace map, associating prefixes with URIs + : @param options currently not evaluated + : @return a copy of the element with namespace bindings added + :) +declare function ns:addNamespaceContext($elem as element(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as element() { + element {node-name($elem)} { + if ($options?discard) then () else + $elem/in-scope-prefixes(.) + ! namespace {.} {namespace-uri-for-prefix(., $elem)}, + $nsmap/z:ns/namespace {@prefix} {@uri}, + $elem/@*, + ($options?baseUri ! attribute xml:base {.})[not($elem/@xml:base)], + $elem/node() + } +}; + +(:~ + : Returns the namespace nodes of an element. + : + : @param elem an element + : @return a copy of its namespace nodes + :) +declare function ns:getNamespaceNodes($elem as element()) + as node()* { + $elem/in-scope-prefixes(.)[string()] + ! namespace {.} {namespace-uri-for-prefix(., $elem)} +}; + + + + + diff --git a/docs/generate_tables/xco-rdesc.xqm b/docs/generate_tables/xco-rdesc.xqm new file mode 100644 index 000000000..067ed66bb --- /dev/null +++ b/docs/generate_tables/xco-rdesc.xqm @@ -0,0 +1,142 @@ +(: + : xco-resc - functions creating rdesc component descriptors + :) +module namespace rd="http://www.parsqube.de/ns/xco/rdesc"; + +import module namespace cd="http://www.parsqube.de/ns/xco/desc" + at "xco-desc.xqm"; +import module namespace cn="http://www.parsqube.de/ns/xco/comp-names" + at "xco-comp-names.xqm"; +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Returns for each given schema component the component descriptor + : and the component descriptors of all other schema components on + : which the given component depends. + : + : Input schema components may be global element declarations, type + : definitions and group definitions. + : + : A component depends on another comonent if it directly or indirectly + : references it (base type reference, group reference, attribute group + : reference). + : + : The descriptors of components which the given component depends + : are arranged in a map, using the component kind as keys (group, + : attributeGroup, element, attribute, type, localtype). + : + : @param comps schema components + : @return component descriptors of those components, and of those + : components on which they depend + :) +declare function rd:getRequiredCompDescs($comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as map(xs:string, item()*) { + let $options := map:put($options, 'deepResolve', false()) + for $comp in $comps + let $compDescs := rd:getRequiredCompDescsREC($comp, (), $nsmap, $schemas, $options) + let $requiredRaw := $compDescs => tail() + let $required := + if (empty($requiredRaw)) then () else + (: Arrange the required descriptors in a map :) + let $groups := $requiredRaw/self::z:group + let $attributeGroups := $requiredRaw/self::z:attributeGroup + let $elems := $requiredRaw/self::z:element + let $atts := $requiredRaw/self::z:attribute + let $types := $requiredRaw/(self::z:simpleType, self::z:complexType)[@z:name] + let $localTypes := $requiredRaw/(self::z:simpleType, self::z:complexType)[@z:typeID] + return map:merge(( + map:entry('group', $groups)[$groups], + map:entry('attributeGroup', $attributeGroups)[$attributeGroups], + map:entry('element', $elems)[$elems], + map:entry('attribute', $atts)[$atts], + map:entry('type', $types)[$types], + map:entry('localType', $localTypes)[$localTypes] + )) + return + map{'main': $compDescs => head(), + 'required': $required} +}; + +(:~ + : Recursive helper function of `rd:getRequiredCompDescs`. + : + : @param comps schema components + : @param namesAvailable the qualified names of component descriptors already + : collected + : @param nsmap a map of normalized namespace bindings + : @param schemas a set of schema elements + : @param options options controlling the processing + : @return component descriptors of the schema components, followed + : by the component descriptors on which the given components depend + :) +declare function rd:getRequiredCompDescsREC( + $comps as element()*, + $namesAvailable as map(xs:string, item()*)?, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as element()* { + let $compDescs := cd:getCompDescs($comps, $nsmap, $options) + let $newNamesAvailable := cn:mergeCompNames(cn:getCompNames($comps), $namesAvailable) + let $requiredCompNamesRaw := rd:getRequiredCompNames($compDescs, $options) + let $requiredCompNames := cn:compNamesExcept($requiredCompNamesRaw, $newNamesAvailable) + let $requiredCompsMap := cn:resolveCompNames($requiredCompNames, $schemas, true()) + let $requiredComps := $requiredCompsMap?* + return ( + $compDescs, + if (empty($requiredComps)) then () else + rd:getRequiredCompDescsREC($requiredComps, $newNamesAvailable, $nsmap, $schemas, $options) + [$requiredComps] + ) +}; + +(:~ + : Returns the qualified names of components referenced by a set of component + : descriptors. The component names are returned as a map with component kinds + : as keys and a sequence of qualified component names as values. + : + : Component kinds used as keys: group, attributeGroup, element, attribute, + : type, localType. + : + : @param compDescs component descriptors + : @param options options controlling the processing + : @return a map of qualified component names + :) +declare function rd:getRequiredCompNames($compDescs as element()*, + $options as map(xs:string, item()*)) + as map(xs:string, item()*) { + map:merge( + let $groupNames := $compDescs//z:group/@z:ref/resolve-QName(., ..) + let $attributeGroupNames := $compDescs//z:attributeGroup/@z:ref/resolve-QName(., ..) + let $elemNames := $compDescs//z:element/@z:ref/resolve-QName(., ..) + let $attNames := $compDescs//z:attribute/@z:ref/resolve-QName(., ..) + let $typeNames := ( + $compDescs//@z:base/resolve-QName(., ..), + $compDescs//@z:itemType/resolve-QName(., ..), + for $memberTypes in $compDescs//@z:memberTypes return + tokenize($memberTypes) ! resolve-QName(., $memberTypes/..), + + (: Deep resolving (content type names) dependent on $options?deepResolve ... :) + $compDescs//@z:type[$options?deepResolve]/resolve-QName(., ..)) + + [not(ns:isQNameBuiltin(.))] + => distinct-values() + let $localTypeNames := $compDescs//@z:typeID + return ( + map:entry('group', $groupNames)[exists($groupNames)], + map:entry('attributeGroup', $attributeGroupNames)[exists($attributeGroupNames)], + map:entry('element', $elemNames)[exists($elemNames)], + map:entry('attribute', $attNames)[exists($attNames)], + map:entry('type', $typeNames)[exists($typeNames)], + map:entry('localType', $localTypeNames)[exists($localTypeNames)] + ) + ) +}; diff --git a/docs/generate_tables/xco-report-util.xqm b/docs/generate_tables/xco-report-util.xqm new file mode 100644 index 000000000..7c4a6b812 --- /dev/null +++ b/docs/generate_tables/xco-report-util.xqm @@ -0,0 +1,7 @@ +(: + : xco-report-util - utility functions supporting the creation of reports + :) +module namespace ru="http://www.parsqube.de/ns/xco/report-util"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + diff --git a/docs/generate_tables/xco-reporter.xqm b/docs/generate_tables/xco-reporter.xqm new file mode 100644 index 000000000..30e94a313 --- /dev/null +++ b/docs/generate_tables/xco-reporter.xqm @@ -0,0 +1,335 @@ +(: + : xco-reporter - funcgtions creating reports + :) +module namespace rp="http://www.parsqube.de/ns/xco/reporter"; + +import module namespace df="http://www.parsqube.de/ns/xco/def" + at "xco-def.xqm"; + +import module namespace dm="http://www.parsqube.de/ns/xco/domain" + at "xco-domain.xqm"; + +import module namespace ed="http://www.parsqube.de/ns/xco/edesc" + at "xco-edesc.xqm"; + +import module namespace rd="http://www.parsqube.de/ns/xco/rdesc" + at "xco-rdesc.xqm"; + +import module namespace cd="http://www.parsqube.de/ns/xco/desc" + at "xco-desc.xqm"; + +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" +at "xco-namespace.xqm"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +import module namespace dg="http://www.parsqube.de/ns/xco/debug" + at "xco-debug.xqm"; + +import module namespace hl="http://www.parsqube.de/ns/xco/html" + at "xco-html.xqm"; + +import module namespace sf="http://www.parsqube.de/ns/xco/string-filter" + at "xco-sfilter.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(: + : + : e d e s c r e p o r t + : ======================== + :) +(:~ + : Create an edesc report. It contains expanded component descriptors. + : + : @param comps schema components + : @param nsmap a map of namespace bindings + : @param schemas schemas to be evaluated + : @param options options controlling the processing + : @return a report + :) +declare function rp:expandedCompDescsReport( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as element()? { + let $forEachDomain := exists($options?domains) (: $options?forEachDomain :) + return + (: Write one file for each domain :) + if ($forEachDomain) then ( + let $_LOG := 'Going to write edesc report files for each domain' + let $_WRITE := ed:writeExpandedCompDescsPerDomain($comps, $nsmap, $schemas, $options) + let $_LOG := 'edesc report files written for each domain' + return () + ) + (: Write a single file (if $options?ofile), or return the report :) + else + + let $ofile := $options?ofile + (: Create expanded component descriptors :) + let $reports := + ed:getExpandedCompDescs($comps, $nsmap, $schemas, $options) + let $_DEBUG := trace('*** Expanded component descriptors written ') + let $creports := + if ($options?skipAnno) then $reports/u:removeAnno(.)/u:prettyNode(.) + else $reports + (: Create schema reports :) + let $schemaReports := + for $crs in $creports + group by $baseUri := $crs/base-uri(.) + return + { + if ($options?skipAnno) then () else + let $schema := $schemas[base-uri(.) eq $baseUri] + return $schema/xs:annotation[1]/cd:annotationDescriptor(.), + {$crs} + } + (: Integrate schema reports :) + let $reportRaw := + { + $schemaReports + } + /ns:addNamespaceContext(., $nsmap, ()) /u:prettyNode(.) + (: Optional grouping by domains :) + let $reportDomains := + rp:expandedCompDescsReport_groupByDomains($reportRaw, $options) + (: Perform pruning :) + let $report := + let $skipAtts := $options?skipAtts + let $keepAtts := $options?keepAtts + return + if (empty(($skipAtts, $keepAtts))) then $reportDomains + else u:removeZAtts($reportDomains, $keepAtts, $skipAtts) + let $_DEBUG := trace('ofile='||$ofile|| + '; #elems(reportRaw)='||count($reportRaw//*)|| + '; count(reports)='||count($reports)|| + '; count(schemaReports)='||count($schemaReports)|| + '; #elems(reportDomains)='||count($reportDomains//*)|| + '; #elems(report)='||count($report//*)) + return + (: Either write file or return the report :) + if ($ofile) then file:write($ofile, $report, map{'indent': 'yes'}) + else $report +}; + +(:~ + : Edits an edesc report, grouping the schema reports by domain + : and wrapping them in elements. + :) +declare function rp:expandedCompDescsReport_groupByDomains( + $report as element(), + $options as map(xs:string, item()*)) + as element(report) { + let $domains := $options?domains + return if (not($domains)) then $report else + + let $domainReports := + let $xsdMap := map:merge($report/z:schema/map:entry(@filePath, .)) + for $domain in $domains/domain + let $xsds := $domain/content/xsd + order by $domain/@name ! lower-case(.) + return + $domain/{ + ns:getNamespaceNodes($report), + attribute z:name {@name}, + attribute z:id {@id}, + attribute countXsds {count($xsds)}, + for $xsd in $xsds + let $fpath := $xsd/@filePath + let $xsdReport := $xsdMap($fpath) + return $xsdReport + } + return + element {node-name($report)} { + ns:getNamespaceNodes($report), + $report/@*, + attribute countDomains {count($domainReports)}, + $domainReports + } +}; + +(: + : + : r d e s c r e p o r t + : ======================== + :) +(:~ + : Creates an rdesc report. Each component is described by a component + : descriptor accompanied by a complete set of directly or indirectly + : referenced other component descriptors. This report format is used + : as an intermediate when creating expanded component descriptors. + : + : @param comps schema components + : @param nsmap a map of namespace bindings + : @param schemas schemas to be evaluated + : @param options options controlling the processing + : @return a report + :) +declare function rp:requiredCompDescsReport( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as element() { + let $_DEBUG := trace('RDESC-REPORT: #comps='||count($comps)) + let $reports1 := $comps ! rd:getRequiredCompDescs(., $nsmap, $schemas, $options) + let $_DEBUG := trace('RDESC-REPORT: reports1 created') + let $reports2 := $reports1 ! rp:requiredCompDescsElement(.) + let $_DEBUG := trace('RDESC-REPORT: reports2 created') + let $reports := $reports2 + let $creports := + if ($options?skipAnno) then $reports/u:removeAnno(.)/u:prettyNode(.) + else $reports/u:prettyNode(.) + let $_DEBUG := trace('Reports cleaned') + let $report := + { + $creports + }/ns:addNamespaceContext(., $nsmap, ()) + return $report +}; + +(: + : + : d e s c r e p o r t + : ====================== + :) +(:~ + : Creates a desc report. Each component is described by a component + : descriptor. Referenced components are not resolved. + : + : @param comps schema components + : @param nsmap a map of namespace bindings + : @param schemas schemas to be evaluated + : @param options options controlling the processing + : @return a report + :) +declare function rp:compDescsReport( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as element()? { + let $reports := $comps ! cd:getCompDescs(., $nsmap, $options) + let $creports := + if ($options?skipAnno) then $reports/u:removeAnno(.)/u:prettyNode(.) + else $reports/u:prettyNode(.) + let $report := + { + $creports + }/ns:addNamespaceContext(., $nsmap, ()) + let $ofile := $options?ofile + return + (: Either write file or return the report :) + if ($ofile) then file:write($ofile, $report, map{'indent': 'yes'}) + else $report + +}; + +(: + : + : d e f r e p o r t + : ==================== + :) +(:~ + : Creates a def report. The components contains the selected + : schema comonents in normalized form. + : + : @param comps schema components + : @param nsmap a map of namespace bindings + : @param schemas schemas to be evaluated + : @param options options controlling the processing + : @return a report + :) + +declare function rp:compDefReport( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as element()? { + let $forEachDomain := exists($options?domains) + return + (: Write one file for each domain :) + if ($forEachDomain) then ( + let $_LOG := 'Going to write def report files for each domain containing selected components' + let $_WRITE := df:writeCompDefDomainReports($comps, $nsmap, $schemas, $options) + let $_LOG := 'def report files written for each domain' + return () + ) + (: Write a single file (if $options?ofile), or return the report :) + else + df:writeCompDefReport($comps, $nsmap, $schemas, $options) +}; + +(: + : c o n t a b r e p o r t + : ========================== + :) +declare function rp:contabReport( + $comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as item()* { + let $edescReport := $options?edescReport + let $edescReportDir := $options?edescReportDir + let $edescReportDirDynamic := $options?edescReportDirDynamic + let $useOptions := map:put($options, 'skipAnno', false()) + (: The underlying edesc report is either retrieved or created :) + let $xmlReportDir := ($edescReportDir, $edescReportDirDynamic)[1] + let $xmlReport := + if ($edescReportDir) then () + else if ($edescReport) then + let $uri := $edescReport ! u:normalizeUri(., ()) + return + if (not(file:exists($uri))) then error((), 'ERROR - edesc report file not found: ', $uri) + else if (not(doc-available($uri))) then error((), 'ERROR - cannot read edesc report file: ', $uri) + else + let $report := doc($uri)/* + let $_DEBUG := trace('*** edesc report read from file: '||$uri) + return $report + else + let $_DEBUG := trace('Write edesc report(s)') + let $report := rp:expandedCompDescsReport($comps, $nsmap, $schemas, $useOptions) + let $_DEBUG := trace('Writing of edesc report(s) finished') + return $report + let $_WDEBUG := $xmlReport ! dg:WRITE_FILE(., 'EDESC-REPORT.XML', 'edesc-report', 'yes', $options) + let $_LOG := trace('Write contab reports') + let $htmlReport := hl:htmlReport('contab', $xmlReport, $xmlReportDir, $options) ! u:prettyNode(.) + let $_LOG := trace('Writing of contab reports fininshed') + return () +}; + +(: + : U t i l i t i e s + : ================== + :) + +(:~ + : Maps a requiredCompDescs map to an element. + :) +declare function rp:requiredCompDescsElement($reqCompDescsMap as map(xs:string, item()*)) + as element(report) { + { +
    {$reqCompDescsMap?main}
    , + { + for $key in $reqCompDescsMap?required ! map:keys(.) + order by $key + let $compDescs := $reqCompDescsMap?required($key) + let $count := count($compDescs) + return + element {$key||'s'} {attribute count {$count}, $compDescs} + } + }
    +}; + + \ No newline at end of file diff --git a/docs/generate_tables/xco-required-comp-descriptor.xqm b/docs/generate_tables/xco-required-comp-descriptor.xqm new file mode 100644 index 000000000..99c343df6 --- /dev/null +++ b/docs/generate_tables/xco-required-comp-descriptor.xqm @@ -0,0 +1,105 @@ +(: + : xco-required-comp-descriptor - functions creating component descriptors + :) +module namespace ed="http://www.parsqube.de/ns/xco/required-comp-descriptor"; + +import module namespace cd="http://www.parsqube.de/ns/xco/comp-descriptor" + at "xco-comp-descriptor.xqm"; +import module namespace cn="http://www.parsqube.de/ns/xco/comp-names" + at "xco-comp-names.xqm"; +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; +import module namespace sd="http://www.parsqube.de/ns/xco/simple-type-description" + at "xco-stype-description.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Returns for each given schema component the component descriptor + : and the component descriptors of all other schema components on + : which it depends. + : + : @param comps schema components + : @return component descriptors + :) +declare function ed:getRequiredCompDescs($comps as element()*, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as map(xs:string, item()*) { + let $_DEBUG := trace('GET_REQUIRED_COMP_DESCS called') + let $_DEBUG := trace('COMP-NAME='||$comps[1]/@name) + for $comp in $comps + let $_DEBUG := $comp/trace('*** Get required components for '||name()||': '||@name) + let $compDescs := ed:getRequiredCompDescsREC($comp, (), $nsmap, $schemas, $options) + let $requiredRaw := $compDescs => tail() + let $required := + if (empty($requiredRaw)) then () else + + let $groups := $requiredRaw/self::z:group + let $attributeGroups := $requiredRaw/self::z:attributeGroup + let $elems := $requiredRaw/self::z:element + let $atts := $requiredRaw/self::z:attribute + let $types := $requiredRaw/(self::z:simpleType, self::z:complexType)[@z:name] + let $localTypes := $requiredRaw/(self::z:simpleType, self::z:complexType)[@z:typeID] + return map:merge(( + map:entry('group', $groups)[$groups], + map:entry('attributeGroup', $attributeGroups)[$attributeGroups], + map:entry('element', $elems)[$elems], + map:entry('attribute', $atts)[$atts], + map:entry('type', $types)[$types], + map:entry('localType', $localTypes)[$localTypes] + )) + return + map{'main': $compDescs => head(), 'required': $required} +}; + +declare function ed:getRequiredCompDescsREC( + $comps as element()*, + $namesAvailable as map(xs:string, item()*)?, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as element()* { + let $compDescs := cd:getCompDescs($comps, $nsmap, $options) + let $newNamesAvailable := cn:mergeCompNames(cn:getCompNames($comps), $namesAvailable) + let $requiredCompNamesRaw := ed:getRequiredCompNames($compDescs, $options) + let $requiredCompNames := cn:compNamesExcept($requiredCompNamesRaw, $newNamesAvailable) + let $requiredCompsMap := cn:resolveCompNames($requiredCompNames, $schemas, true()) + let $requiredComps := $requiredCompsMap?* + return ( + $compDescs, + if (empty($requiredComps)) then () else + ed:getRequiredCompDescsREC($requiredComps, $newNamesAvailable, $nsmap, $schemas, $options) + [$requiredComps] + ) +}; + +declare function ed:getRequiredCompNames($compDescs as element()*, + $options as map(xs:string, item()*)) + as map(xs:string, item()*) { + map:merge( + let $groupNames := $compDescs//z:group/@z:ref/resolve-QName(., ..) + let $attributeGroupNames := $compDescs//z:attributeGroup/@z:ref/resolve-QName(., ..) + let $elemNames := $compDescs//z:element/@z:ref/resolve-QName(., ..) + let $attNames := $compDescs//z:attribute/@z:ref/resolve-QName(., ..) + let $typeNames := ( + $compDescs//@z:base/resolve-QName(., ..), + $compDescs//@z:itemType/resolve-QName(., ..), + for $memberTypes in $compDescs//@z:memberTypes return + tokenize($memberTypes) ! resolve-QName(., $memberTypes/..) + )[not(namespace-uri-from-QName(.) eq $co:URI_XSD)] + => distinct-values() + let $localTypeNames := $compDescs//@z:typeID + return ( + map:entry('group', $groupNames)[exists($groupNames)], + map:entry('attributeGroup', $attributeGroupNames)[exists($attributeGroupNames)], + map:entry('element', $elemNames)[exists($elemNames)], + map:entry('attribute', $attNames)[exists($attNames)], + map:entry('type', $typeNames)[exists($typeNames)], + map:entry('localType', $localTypeNames)[exists($localTypeNames)] + ) + ) +}; diff --git a/docs/generate_tables/xco-schema-resolver.xqm b/docs/generate_tables/xco-schema-resolver.xqm new file mode 100644 index 000000000..b8694b1cd --- /dev/null +++ b/docs/generate_tables/xco-schema-resolver.xqm @@ -0,0 +1,61 @@ +module namespace sr="http://www.parsqube.de/ns/xco/schema-resolver"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" +at "xco-util.xqm"; + +(:~ + : Returns a schema along with all other schemas obtained by + : recursively resolveing all includes and imports. + : @param global only top-level element declarations are considered + : @return schema components matching the component type specific name filter + :) +declare function sr:resolveSchemas($uris as xs:string+) + as element(xs:schema)* { + (: sr:resolveSchemas_($uri, (), ()) :) + let $uris2 := $uris ! u:normalizeUri(., ()) + let $_LOG := trace('Resolve schema imports / inclusions') + let $schemas := sr:resolveSchemas_($uris2 => head(), $uris2 => tail(), ()) + let $_LOG := trace('Resolving finished') + return + $schemas +}; + +declare function sr:resolveSchemas_($uri as xs:string, + $furtherUris as xs:string*, + $visited as xs:string*) + as item()* { + if (not(file:exists($uri))) then error((), 'Cannot find schema at this URI: '||$uri) else + + let $node := doc($uri)[not($uri = $visited)]/* + let $bu := $node/base-uri(.) ! u:normalizeUri(., ()) + let $newVisited := ($visited, $bu) + let $furtherUris2 := + $node/(xs:include, xs:import)/@schemaLocation/u:normalizeUri(., $bu) + ! sr:editSchemaLocation(.) + [not(. = $furtherUris)] + let $newFU := ($furtherUris, $furtherUris2) + return ( + $node, + sr:resolveSchemas_(head($newFU), tail($newFU), $newVisited)[exists($newFU)] + ) +}; + +declare function sr:editSchemaLocation($schemaLocation) { + if (file:exists($schemaLocation)) then $schemaLocation else + let $_DEBUG := trace($schemaLocation, '*** Imported/included schema not found: ') + let $try := $schemaLocation + ! replace(., '/siri/siri_model/', '/siri/xsd/siri_model/', 'i') + ! replace(., '/xsd/wsdl/siri/', '/xsd/siri/', 'i') + ! replace(., '/xsd/wsdl/siri_utility/', '/xsd/siri_utility/', 'i') + ! replace(., '/xsd/wsdl/netex_service/', '/xsd/netex_service/', 'i') + ! replace(., 'siriSg.xsd', 'NeTEx_siri_SG.xsd', 'i') + ! replace(., '(/NeTEx/.*)/siri.xsd', '$1/NeTEx_siri.xsd', 'i') + let $out := + if (file:exists($try)) then $try + else $try ! replace(., '-v\d\.\d', '') + let $_DEBUG := trace($out, '*** Path of imported/included schema edited: ') + return $out +}; + + + diff --git a/docs/generate_tables/xco-sfilter.xqm b/docs/generate_tables/xco-sfilter.xqm new file mode 100644 index 000000000..d557c2384 --- /dev/null +++ b/docs/generate_tables/xco-sfilter.xqm @@ -0,0 +1,303 @@ +module namespace sf="http://www.parsqube.de/ns/xco/string-filter"; + +(: + : C o m p i l e s t r i n g f i l t e r + : =========================================== + :) + +(:~ + : Compiles a string filter into a structured representation. + : The representation is a element with the following child elements: + : include: a set of regexes and/or strings or substrings to be matched + : exclude: a set of regexes and/or strings or substrings which must not be matched + : + : @param sfilter a string filter string + : @return a map representing the string filter + :) +declare function sf:compileStringFilter( + $sfilter as xs:string?) + as element(stringFilter)? { + let $itemsAndFlags := sf:splitStringIntoItemsAndFlags($sfilter, '#') + let $flags := $itemsAndFlags[1] + let $items := subsequence($itemsAndFlags, 2) + + (: global flags :) + let $ignoreCase := not(contains($flags, 'c')) + let $patternIsRegex := contains($flags, 'r') + let $addAnchors := not(contains($flags, 'A')) + + let $patterns := $items ! replace(., '^\s+|\s+$', '')[string()] + return if (empty($patterns)) then () else + + let $patternsPlus := $patterns[not(starts-with(., '~'))] + let $patternsMinus := $patterns[starts-with(., '~')] ! substring(., 2) + return + if (empty(($patternsPlus, $patternsMinus))) then () else + { + if (empty($patternsPlus)) then () else + {sf:compileSfPatternSet( + $patternsPlus, $ignoreCase, $patternIsRegex, $addAnchors) + }, + if (empty($patternsMinus)) then () else + {sf:compileSfPatternSet( + $patternsMinus, $ignoreCase, $patternIsRegex, $addAnchors) + } + } +}; + +(:~ + : Translates a list of string filter patterns into a structured + : representation. A pattern is a glob pattern or a regular expression. + : The structured representation is a map. + : + : @param patterns a list of patterns + : @param ignoreCase if true, regex matching ignores case + : @param patternIsRegex if true, patterns are interpreted as regular + : expressions, otherwise as glob patterns + : @param addAnchors if true, by default glob patterns are translated + : into regular expressions with anchors indicating the begin and + : end of the string; the default can be overridden by flags 'a' + : (add anchors) and 'A' (do not add anchors). + : @return a map with possible entries 'empty', 'regexes', 'flags', + : 'strings', 'substrings'. + :) +declare function sf:compileSfPatternSet($patterns as xs:string*, + $ignoreCase as xs:boolean?, + $patternIsRegex as xs:boolean?, + $addAnchors as xs:boolean?) + as element()* { + let $literals := + if ($patternIsRegex) then () else $patterns[not(matches(., '[@*?\\]'))] + let $literalsEff := + if (not($ignoreCase)) then $literals else $literals ! lower-case(.) + (: each regex is described by a map with keys 'expr' and 'flags' :) + let $regexes := + for $pattern in $patterns[not(. = $literals)] + let $regexAndFlags := + sf:patternToRegexAndFlags($pattern, $ignoreCase, $patternIsRegex, $addAnchors) + return + + return ( + {$regexes}, + if (empty($literals)) then () else + + let $key := if ($addAnchors) then 'strings' else 'substrings' + return + element {$key} { + attribute ignoreCase {$ignoreCase}, + $literalsEff ! {.}} + ) +}; + +(:~ + : Maps a pattern string to a regex string and a flags string. + : The pattern string may contain flags, separted from the + : pattern itself by a '@'. + : + : Supported flags: + : a/A - add anchors / do not add anchors + : r/R - pattern is regex / is not regex + : c/C - evaluate case-sensitively / not case-sensitively + : + : The parameters $ignoreCase, $patternIsRegex, $addAnchors + : provide default values for flags. + : + : The return value consists of the regex and optional regex flags, + : which are either the empty string or 'i' meaning case-insensitive + : evaluation. + :) +declare function sf:patternToRegexAndFlags( + $pattern as xs:string, + $ignoreCase as xs:boolean?, + $patternIsRegex as xs:boolean?, + $addAnchors as xs:boolean?) + as xs:string+ { + let $exprAndFlags := + if (not(contains($pattern, '@'))) then $pattern (: no flags :) + else + let $exprAndFlags := sf:splitStringAtDoubleEscapableChar($pattern, '@') + let $expr := $exprAndFlags[1] + let $flags := $exprAndFlags[2] + return ($expr, $flags) + let $expr := $exprAndFlags[1] + let $flags := $exprAndFlags[2] + let $regexAndFlags := + (: no flags :) + if (not($flags)) then + let $regex := + if ($patternIsRegex) then $expr + else $expr ! sf:globToRegex(., 'A'[not($addAnchors)]) + let $regexFlags := 'i'[$ignoreCase] + return ($regex, $regexFlags) + else + let $patternIsRegexEff := + if ($flags ! matches(., 'r', 'i')) then contains($flags, 'r') + else $patternIsRegex + let $addAnchorsEff := + if ($flags ! matches(., 'a', 'i')) then not(contains($flags, 'A')) + else $addAnchors + let $ignoreCaseEff := + if ($flags ! matches(., 'c', 'i')) then not(contains($flags, 'c')) + else $ignoreCase + let $regexFlags := 'i'[$ignoreCaseEff] + let $regexExpr := + if ($patternIsRegexEff) then $expr + else $expr ! sf:globToRegex(., 'A'[not($addAnchorsEff)]) + return ($regexExpr, $regexFlags) + return $regexAndFlags +}; + +(: + : M a t c h s t r i n g f i l t e r + : ======================================= + :) + +(:~ + : Matches a string against a string filter. The filter has been constructed + : by function f:compileStringFilter. + : + : @param string the string to match + : @param filter the compiled string filter + : @return true or false, if the string matches, does not match, the filter + :) +declare function sf:matchesStringFilter($string as item(), + $filter as element(stringFilter)?) + as xs:boolean { + if (empty($filter)) then true() else + let $include := $filter/include + let $exclude := $filter/exclude + return + (empty($include) or $include/sf:matchesSfPatternSet($string, .)) and + (empty($exclude) or not($exclude/sf:matchesSfPatternSet($string, .))) +}; + +(:~ + : Matches a string against a string filter pattern set. The pattern set + : is represented by an element with the following child elements: + : - regexes: contains a sequence of elements, each with attributes @expr and @flags + : - strings: contains a sequence of strings, wrapped in elements; + : matching requires that the test string is equal to one of these; + : @ignoreCase=true/false indicates case-sensitivity + : - substrings: contains a sequence of strings, wrapped in elements; + : matching requires that the test string contains one of these; + : @ignoreCase=true/false indicates case-sensitivity + : + : @param string the string to match + : @param stringFilter a compiled string filter + : @return true if the string filter is matched, false otherwise + :) +declare function sf:matchesSfPatternSet($string as xs:string, + $patternSet as element()) + as xs:boolean { + let $stringEff := if ($patternSet/(strings, substring)/@ignoreCase = 'true') then lower-case($string) else $string + return + $patternSet/strings/* = $stringEff + or (some $sstr in $patternSet/substrings/* satisfies + contains($stringEff, $sstr)) + or (some $r in $patternSet/regexes/regex satisfies + matches($string, $r/@expr, $r/@flags)) +}; + +(: + : U t i l i t y f u n c t i o n s + : ================================== + :) + +(:~ + : Splits a string into items and flags. The optional flags are separated + : from the items by a # character. Doubled # characters are interpreted as + : literal characters which do not separate items and flags. + : + : The item text is tokenized into items separated by whitespace (default) + : or one of the characters ,;:/. A non-whitespace separator is assumed if + : contained by the flag string. + : + : Example: "foo bar zoo" + : => flags="", three items="foo", "bar", "zoo" + : + : Example: "foo##bar#c" + : => flags="c", one item="foo#bar" + : + : Example: "foo bar, zoo #,c" + : => flags=",c", two items="foo bar", "zoo" + : + : Example: "foo bar; zoo #c;" + : => flags="c;", two items="foo bar", "zoo" + : + : Example: "foo:bar, zoo #:" + : => flags=":", two items="foo", "bar, zoo" + : + : @param string the string to be split + : @return a sequence of strings; the first one represents the flags, which + : may be a zero-length string; all following items represent the items + : extracted from the string + :) +declare function sf:splitStringIntoItemsAndFlags($string as xs:string, + $char as xs:string) + as xs:string+ { + let $concatAndFlags := sf:splitStringAtDoubleEscapableChar($string, $char) + let $concat := $concatAndFlags[1] + let $flags := $concatAndFlags[2] + return + if (tokenize($flags) = ('fulltext', 'ftext', 'ft')) then ($flags, $concat) + else + + let $sep := + if (not(matches($flags, '[,;:/]'))) then () else + replace($flags, '^.*([,;:/]).*', '$1') ! substring(., 1, 1) + return ( + $flags, + if ($sep) then tokenize($concat, '\s*'||$sep||'\s*') else tokenize($concat)) +}; + +(:~ + : Returns the substrings preceding and following the first occurrence of a + : character ($char) which is not escaped by repeating it. (In other words: + : the first occurrence of $char which is either not repeated or repeated an + : uneven number of times.) If the string does not contain the character or + : any occurrence is repeated an even number of times), the original string + : and a zero-length string are returned. + : + : The first substring returned is edited by replacing any doubled occurrence + : of the character with a single occurrence. (Note that the second + : substring is not edited.) + : + : @param string the string to be analyzed + : @param char the character separating the substrings + : @return sequence of two strings: the string preceding and + : the string following the character + :) +declare function sf:splitStringAtDoubleEscapableChar( + $string as xs:string, + $char as xs:string) + as xs:string+ { + if (not(contains($string, $char))) then ($string, '') + else if (not(contains($string, $char||$char))) then ( + substring-before($string, $char), substring-after($string, $char)) + else + let $patternBefore := '^('||$char||$char||'|[^'||$char||'])+' + return + let $before := replace($string, '('||$patternBefore||').*', '$1') + let $after := substring($string, string-length($before) + 2) + return ($before ! replace(., $char||$char, $char), $after) +}; + +(:~ + : Maps a glob pattern to a regular expression. + : + : @param glob a glob pattern + : @param flags flags controlling the evaluation; + + : @return the equivalent regular expession + :) +declare function sf:globToRegex($glob as xs:string, $flags as xs:string?) + as xs:string { + let $addAnchors := not(contains($flags, 'A')) return + + $glob + ! replace(., '\\s', ' ') + ! replace(., '[.+|\\(){}\[\]\^$]', '\\$0') + ! replace(., '\*', '.*') + ! replace(., '\?', '.') + ! (if ($addAnchors) then concat('^', ., '$') else .) +}; diff --git a/docs/generate_tables/xco-stype-description.xqm b/docs/generate_tables/xco-stype-description.xqm new file mode 100644 index 000000000..addf83a31 --- /dev/null +++ b/docs/generate_tables/xco-stype-description.xqm @@ -0,0 +1,213 @@ +(: + : xco-stype-description - functions creation simple type descriptions + :) +module namespace sd="http://www.parsqube.de/ns/xco/simple-type-description"; + +import module namespace ed="http://www.parsqube.de/ns/xco/edesc" + at "xco-edesc.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; +import module namespace sf="http://www.parsqube.de/ns/xco/comp-finder" + at "xco-comp-finder.xqm"; +import module namespace u="http://www.parsqube.de/ns/xco/util" + at "xco-util.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Maps a type name to a simple type description. If the type + : name identifies a complex type with simple content, the + : simple type used by the complex type is described. + : + : @param name a qualified type name + : @param nsmap a map of namespace bindings + : @param schemas the schemas to be evaluated + : @param options options controlling the processing + : @return a type description, or the empty sequence if the name does not + : refer to a simple type or a complex type with simple content + :) +declare function sd:typeNameToTypeDescription($name as xs:QName, + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as xs:string? { + if (ns:isQNameBuiltin($name)) then + ns:normalizeQName($name, $nsmap) ! string() + else + + let $typeDef := sf:findType($name, $schemas) + let $stypeDef := u:extractSimpleType($typeDef, $schemas) + where exists($stypeDef) + return + if ($stypeDef instance of xs:anyAtomicType) then + sd:typeNameToTypeDescription($stypeDef, $nsmap, $schemas, $options) + else + let $edesc := ed:getExpandedCompDescs($stypeDef, $nsmap, $schemas, $options) + let $tdesc := $edesc ! sd:edescToTypeDescription($edesc) + return $tdesc +}; + +(:~ + : Maps a type definition to a simple type description. The empty sequence is + : returned unless the type definition is a simple type or a complex type with + : simple content. + : + : @param stypeTree extended descriptor of a simple type + : @return the text of a description + :) +declare function sd:typeDefToTypeDescription($type as element(), + $nsmap as element(z:nsMap), + $schemas as element(xs:schema)*, + $options as map(xs:string, item()*)) + as xs:string? { + let $stype := u:extractSimpleType($type, $schemas) + return + if ($stype instance of xs:anyAtomicType) then + sd:typeNameToTypeDescription($stype, $nsmap, $schemas, $options) + else + let $edesc := ed:getExpandedCompDescs($stype, $nsmap, $schemas, $options) + let $tdesc := $edesc ! sd:edescToTypeDescription($edesc) + return $tdesc +}; + +(:~ + : Maps an extended descriptor of a type definition to a textual description. + : + : @param stypeTree extended descriptor of a simple type + : @return the text of a description + :) +declare function sd:edescToTypeDescription($edesc as element()) + as xs:string { + let $tdesc := sd:edescToTypeDescriptionREC($edesc) + return $tdesc +}; + +(:~ + : Recursive helper function of `edescToTypeDescription`. + :) +declare function sd:edescToTypeDescriptionREC($n as node()) + as xs:string? { + let $result := + typeswitch($n) + case element(z:simpleType) return + $n/* ! sd:edescToTypeDescriptionREC(.) + case element(z:annotation) return () + case element(z:list) return + let $itemType := $n/z:itemType + let $itemTypeDesc := + if ($itemType/@z:name) then $itemType/@z:name/string() + else $itemType/* ! sd:edescToTypeDescriptionREC(.) + return + 'List('||$itemTypeDesc||')' + case element(z:union) return + let $memberDescs := $n/z:unionMember/* ! sd:edescToTypeDescriptionREC(.) + return + 'Union('||string-join($memberDescs ! concat('{', ., '}'), ', ')||')' + case element(z:faceted) return + let $baseDesc := $n/z:baseType ! sd:edescToTypeDescriptionREC(.) + let $restrictions := $n/z:restrictions/z:restriction => sd:getRestrictionInfo() + return + $baseDesc||': '||$restrictions + case element(z:baseType) return + if ($n/@z:name) then $n/@z:name + else $n/* ! sd:edescToTypeDescriptionREC(.) + case element(z:builtinType) return $n/@z:name/string() + case element() return () + default return () + return $result +}; + +(:~ + : Transforms a list of restrictions contained by an extended type + : descriptor into a concise textual description. + :) +declare function sd:getRestrictionInfo + ($restrictions as element(z:restriction)*) as xs:string? { + if (empty($restrictions)) then () else + + let $length := for $f in $restrictions/z:length return concat('len=', $f/@z:value) + let $minLength := max($restrictions/z:minLength/@z:value/xs:int(.)) + let $maxLength := min($restrictions/z:maxLength/@z:value/xs:int(.)) + let $minInclusive := max($restrictions/z:minInclusive/@z:value/sd:castToComparable(.)) + let $minExclusive := max($restrictions/z:minExclusive/@z:value/sd:castToComparable(.)) + let $maxInclusive := min($restrictions/z:maxInclusive/@z:value/sd:castToComparable(.)) + let $maxExclusive := min($restrictions/z:maxExclusive/@z:value/sd:castToComparable(.)) + + let $totalDigits := $restrictions/z:totalDigits/@z:value/xs:int(.) + let $totalDigits := if (empty($totalDigits)) then () + else concat('totalDigits=', + string-join(for $t in $totalDigits return string($t), ',')) + let $fractionDigits := $restrictions/z:fractionDigits/@z:value/xs:int(.) + let $fractionDigits := if (empty($fractionDigits)) then () + else concat('fractionDigits=', + string-join(for $t in $fractionDigits return string($t), ',')) + let $minMax := + if (exists(($minInclusive, $minExclusive)) and + exists(($maxInclusive, $maxExclusive))) + then + let $lhs := if (exists($minInclusive) and not($minInclusive < $minExclusive)) + then concat('[', $minInclusive) + else concat('(', $minExclusive) + let $rhs := if (exists($maxInclusive) and not($maxInclusive > $maxExclusive)) + then concat($maxInclusive, ']') + else concat($maxExclusive, ')') + return concat('range=', $lhs, ',', $rhs) + else if (exists($minInclusive) or exists($minExclusive)) then + if (exists($minInclusive) and not($minInclusive < $minExclusive)) + then concat('value>=', $minInclusive) + else concat('value>', $minExclusive) + else if (exists($maxInclusive) or exists($maxExclusive)) then + if (exists($maxInclusive) and not($maxInclusive > $maxExclusive)) + then concat('value<=', $maxInclusive) + else concat('value<', $maxExclusive) + else () + let $enums := string-join( + for $r in $restrictions[z:enumeration][last()]/z:enumeration + order by lower-case($r/@z:value) + return $r/@z:value + , '|') + let $enums := $enums[string()] ! concat('enum=(', ., ')') + let $patterns := + string-join( + $restrictions[z:pattern]/string-join(z:pattern/@z:value, ' OR ') + , ' AND ') + let $patterns := $patterns[string()] ! concat('pattern=#', ., '#') + let $minMaxLength := + if (exists($minLength) and exists($maxLength)) then concat('len=', $minLength, '-', $maxLength) + else if (exists($minLength)) then concat('minLen=', $minLength) + else if (exists($maxLength)) then concat('maxLen=', $maxLength) + else () + let $facets := ( + string-join(($length, $minMaxLength, $minMax, + $totalDigits, $fractionDigits, + $enums, $patterns), '; ')[string()], + '(empty restriction)')[1] + return $facets +}; + +(:~ + : Determines if a given simple type description refers to an enum type. + : + : @param tdesc a simple type description + : @return true or false + :) +declare function sd:isTypeDescriptionEnumDesc($tdesc as xs:string?) + as xs:boolean? { + $tdesc ! contains(., 'enum=') +}; + +(:~ + : Casts a string to a value comparable per < and >. + :) +declare function sd:castToComparable($s as xs:string?) + as item()? { + if ($s castable as xs:date) then xs:date($s) + else if ($s castable as xs:dateTime) then xs:dateTime($s) + else if ($s castable as xs:time) then xs:time($s) + else if ($s castable as xs:double) then number($s) + else if ($s castable as xs:decimal) then number($s) + else if ($s castable as xs:boolean) then xs:boolean($s) ! number(.) + else xs:untypedAtomic($s) +}; + + diff --git a/docs/generate_tables/xco-util.xqm b/docs/generate_tables/xco-util.xqm new file mode 100644 index 000000000..67e590707 --- /dev/null +++ b/docs/generate_tables/xco-util.xqm @@ -0,0 +1,338 @@ +module namespace u="http://www.parsqube.de/ns/xco/util"; +import module namespace cf="http://www.parsqube.de/ns/xco/comp-finder" + at "xco-comp-finder.xqm"; +import module namespace co="http://www.parsqube.de/ns/xco/constants" + at "xco-constants.xqm"; +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" + at "xco-namespace.xqm"; +import module namespace sf="http://www.parsqube.de/ns/xco/string-filter" + at "xco-sfilter.xqm"; + +declare namespace z="http://www.parsqube.de/ns/xco/structure"; + +(:~ + : Transforms a literal string into an equivalent regular + : expression. Rules: + : (1) string "%20" is replaced with \s + : (2) string "." is replaced with \s + : (3) wildcards "?" and "*" are retained + : + : @param literal a literal string + : @return the equivalent regular expression + :) +declare function u:literalToRegex($literal as xs:string) + as xs:string { + $literal + ! replace(., '\.', '\\.') + ! replace(., '[(){}\[\]]', '\\$0') + ! replace(., '%20', '\\s') +}; + +(:~ + : Resolves and normalizes a URI. The URI is resolved against + : an explicit base URI, or against the current work directory, + : if no explicit base URI is specified. + :) +declare function u:normalizeUri($uri as xs:string, $base as xs:string?) + as xs:string { + let $base := ($base, file:current-dir())[1] + return + file:resolve-path($uri, $base) ! replace(., '\\', '/') + ! replace(., '/$', '') + ! replace(., 'file:/*(([^/]:)?/.*)', '$1') +}; + +declare function u:removeAnno($node as node()) { + typeswitch($node) + case document-node() return document {$node/node() ! u:removeAnno(.)} + case element(xs:annotation) | element(z:annotation) return () + case element() return + element {node-name($node)} { + $node/@* ! u:removeAnno(.), + ns:getNamespaceNodes($node), + $node/node() ! u:removeAnno(.) + } + case text() return + $node[not((preceding-sibling::*[1], following-sibling::*[1]) + /self::*:annotation)] + case attribute() return $node + default return $node +}; + +(:~ + : Removes from the deep content of an input node all attributes (1) in a + : namespace matching an optional namespace filter and (2) with a local name + : not matching an optional positive filter or matching an optional negative + : filter. + :) +declare function u:removeAtts($node as node(), + $nsFilter as xs:string?, + $keepFilter as xs:string?, + $discardFilter as xs:string?) + as node() { + let $nsFilterElem := $nsFilter ! sf:compileStringFilter(.) + let $keepFilterElem := $keepFilter ! sf:compileStringFilter(.) + let $discardFilterElem := $discardFilter ! sf:compileStringFilter(.) + return u:removeAttsREC($node, $nsFilterElem, $keepFilterElem, $discardFilterElem) +}; + +(:~ + : Removes from the deep content of an input node all attributes in the z + : namespace with a local name not matching an optional positive filter or + : matching an optional negative filter. + :) +declare function u:removeZAtts($node as node(), + $keepFilter as xs:string?, + $discardFilter as xs:string?) + as node() { + let $nsFilterElem := + sf:compileStringFilter('http://www.parsqube.de/ns/xco/structure http://www.w3.org/XML/1998/namespace') + let $keepFilterElem := $keepFilter ! sf:compileStringFilter(.) + let $discardFilterElem := $discardFilter ! sf:compileStringFilter(.) + return u:removeAttsREC($node, $nsFilterElem, $keepFilterElem, $discardFilterElem) +}; + +(:~ + : Removes from the deep content of an input node all attributes (1) + : in a namespace matching an optional namespace filter and (2) with + : a local name not matching an optional positive filter or matching + : an optional negative filter. + :) +declare function u:removeAttsREC($node as node(), + $nsFilter as element()?, + $keepFilter as element()?, + $discardFilter as element()?) + as node()? { + typeswitch($node) + case document-node() return document {$node/node() ! + u:removeAttsREC(., $nsFilter, $keepFilter, $discardFilter)} + case element() return + element {node-name($node)} { + $node/@* ! u:removeAttsREC(., $nsFilter, $keepFilter, $discardFilter), + $node/node() ! u:removeAttsREC(., $nsFilter, $keepFilter, $discardFilter) + } + case attribute() return + let $ns := namespace-uri($node) + return + if ($nsFilter and not(sf:matchesStringFilter($ns, $nsFilter))) then $node + else + + let $cond := ( + $keepFilter ! sf:matchesStringFilter(local-name($node), .), + $discardFilter ! not(sf:matchesStringFilter(local-name($node), .)) + ) + return + $node[every $c in $cond satisfies $cond] + default return $node +}; + +declare function u:prettyNode($node as node()) { + typeswitch($node) + case document-node() return document {$node/node() ! u:prettyNode(.)} + case element() return + element {node-name($node)} { + $node/@*, + ns:getNamespaceNodes($node), + (: [$node/not(deep-equal(in-scope-prefixes(.), parent::*/in-scope-prefixes(.)))], :) + $node/node() ! u:prettyNode(.) + } + case attribute() return $node + case text() return + $node[not(../*) or matches(., '\S')] + default return $node +}; + +declare function u:copyNode($node as node()) { + typeswitch($node) + case document-node() return document {$node/node()} + case element() return + element {node-name($node)} { + in-scope-prefixes($node) + ! namespace {.} {namespace-uri-for-prefix(., $node)}, + $node/(@*, node()) + } + default return $node +}; + +(:~ + : Modifies a set of schemas, adding to anonymous type definitions + : a @z:typeID attribute. + :) +declare function u:addLocalTypeIds($schemas as element(xs:schema)*) + as element(xs:schema)* { + for $schema at $snr in $schemas/root() + return + copy $schema_ := $schema + modify + let $atypes := $schema_//(xs:simpleType, xs:complexType)[not(@name)] + where $atypes + return ( + for $atype at $tnr in $atypes return + insert node attribute z:typeID {'typedef-'||$snr||'.'||$tnr} into $atype, + insert node attribute xml:base {$schema/base-uri(.)} into $schema_/* + ) + return $schema_/* +}; + +(:~ + : Returns the type category for a given type name. + :) +declare function u:typeCategory($typeName as xs:QName, $schemas as element(xs:schema)*) + as xs:string? { + if (ns:isQNameBuiltin($typeName)) then + if (local-name-from-QName($typeName) = ('any', 'anyAttribute')) then 'at' else 'sb' + else + let $typeDef := cf:findType($typeName, $schemas) + let $typeCat := $typeDef[1] ! u:typeCategory(.) + return $typeCat[1] +}; + +declare function u:typeCategory($type as element()) + as xs:string { + if ($type/self::xs:simpleType) then + if ($type/xs:restriction) then + if (empty($type/xs:restriction/(* except xs:annotation)) + and $type/xs:restriction/@base/resolve-QName(., ..) + ! ns:isQNameBuiltin(.)) then 'se' + else 'sr' + else if ($type/xs:list) then 'sl' + else if ($type/xs:union) then 'su' + else 's?' + else + if ($type/xs:complexContent) then 'cc' + else if ($type/xs:simpleContent) then 'cs' + else + let $children := + $type/(., xs:complexContent/(xs:extension, xs:restriction))/ + (xs:sequence, xs:choice, xs:all, xs:group) + let $atts := + $type/(., xs:complexContent/(xs:extension, xs:restriction))/ + (xs:attribute, xs:attributeGroup) + return + if ($children) then 'cc' + else if ($atts) then 'ca' + else 'ce' +}; + +declare function u:isTypeCategorySimple($typeCategory as xs:string?) + as xs:boolean { + $typeCategory ! starts-with(., 's') +}; + +(:~ + : Maps a type definition to the simple type which it contains. + :) +declare function u:extractSimpleType($typeDef as element()?, + $schemas as element(xs:schema)*) + as item()? { + if (not($typeDef)) then () else + typeswitch($typeDef) + case element(xs:simpleType) return $typeDef + case element(xs:complexType) return + let $extension := $typeDef/xs:simpleContent/xs:extension + where $extension + return + let $localType := $extension/(xs:simpleType, xs:complexType) + return + if ($localType) then $localType/u:extractSimpleType(., $schemas) + else + let $base := $extension/@base/resolve-QName(., ..) + return + if (ns:isQNameBuiltin($base)) then $base else + $base ! cf:findType(., $schemas) + ! u:extractSimpleType(., $schemas) + default return () +}; + +(:~ + : Maps an integer number to a letter representing it (1=a, 2=b, ...). + :) +declare function u:letterNumber($number as xs:integer) + as xs:string { + substring('abcdefghijklmnopqrstuvwxyz', $number, 1) +}; + +(:~ + : Returns a string describing the location of a local type definition. + :) +declare function u:getLocalTypeLocator($type as element(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as xs:string? { + if (not($type/@z:typeID)) then () else + let $globalComp := $type/ancestor::*[parent::xs:schema] + let $globalCompName := $globalComp/@name/resolve-QName(., ..) ! ns:normalizeQName(., $nsmap) + let $globalCompKind := $globalComp/local-name() + let $withinCompPath := + $type/(ancestor::xs:element, ancestor::xs:attribute) + [. >> $globalComp]/ + @name/concat(parent::attribute()/'@', .) => string-join('/') + return + string-join(( + $globalCompKind||'['||$globalCompName||']', + $withinCompPath[string()] + ), '/')||'#'||$type/local-name(.) +}; + +(:~ + : Returns a label identifying a local type definition. + :) +declare function u:getLocalTypeLabel($type as element(), + $nsmap as element(z:nsMap), + $options as map(xs:string, item()*)?) + as xs:string? { + u:getLocalTypeLocator($type, $nsmap, $options) + ! concat(., ' (', $type/@z:typeID, ')') +}; + +(:~ + : Returns the type label of a type descriptor. + :) +declare function u:getDescriptorLocalTypeLabel($desc as element()) + as xs:string? { + $desc/@z:typeID ! concat(../@z:typeLocator, ' (', .,')') +}; + +(:~ + : Returns the type label of a type descriptor as a couple of + :
    elements. (Useful for display in two lines.) + :) +declare function u:getDescriptorLocalTypeLabelDivs($desc as xs:string) + as element(div)+ { + let $suffix := $desc ! replace(., '.*\s*(\(typedef.*)', '$1')[not(. eq $desc)] + let $prefix := $desc ! replace(., '\s*\(.*', '') + return ( +
    {$prefix}
    , + $suffix !
    {.}
    + ) +}; + +(:~ + : Writes a document to the file system. If the folder does not + : yet exist, it is created now. + : + : If no serialization parameters are specified, the output document + : is indented. + : + : @param path the file system path of the output file + : @param doc the documednt to be written (document or element node) + : @serParams optional serialization parameters + : @return the empty sequence + :) +declare function u:writeXmlDoc($path as xs:string, + $doc as node(), + $serParams as map(xs:string, item()*)?) + as empty-sequence() { + let $dir := $path ! replace(., '/[^/]*$', '') + let $_CRDIR := if (file:exists($dir)) then () else file:create-dir($dir) + let $spar := if (exists($serParams)) then $serParams else map{'indent': 'yes'} + return + file:write($path, $doc, $spar) +}; + +declare function u:writeXmlDoc($path as xs:string, + $doc as node()) + as empty-sequence() { + u:writeXmlDoc($path, $doc, ()) +}; + diff --git a/docs/generate_tables/xcore.xq b/docs/generate_tables/xcore.xq new file mode 100644 index 000000000..81d193e04 --- /dev/null +++ b/docs/generate_tables/xcore.xq @@ -0,0 +1,161 @@ +(: + : xcore.xq - command-line interface of the XSD Content Reporter (XCORE) + :) +import module namespace cr="http://www.parsqube.de/ns/xco/comp-reporter" +at "xco-comp-reporter.xqm"; + +import module namespace ci="http://www.parsqube.de/ns/xco/check-input" +at "xco-check-input.xqm"; + +import module namespace cu="http://www.parsqube.de/ns/xco/custom" +at "xco-custom.xqm"; + +import module namespace dg="http://www.parsqube.de/ns/xco/debug" +at "xco-debug.xqm"; + +import module namespace fu="http://www.parsqube.de/ns/xco/file-util" +at "xco-file-util.xqm"; + +import module namespace ns="http://www.parsqube.de/ns/xco/namespace" +at "xco-namespace.xqm"; + +import module namespace sr="http://www.parsqube.de/ns/xco/schema-resolver" +at "xco-schema-resolver.xqm"; + +import module namespace dm="http://www.parsqube.de/ns/xco/domain" + at "xco-domain.xqm"; + +import module namespace u="http://www.parsqube.de/ns/xco/util" +at "xco-util.xqm"; + +declare variable $report external := 'edesc'; (: def | desc | rdesc | edesc | contab | tree :) +declare variable $fnamesExcluded external := ('DATEXIISchema.xsd', 'OJP_deprecated.xsd'); +declare variable $dir external := (); +declare variable $dnamesExcluded external := (); +declare variable $xsd external := (); (: '/projects/sbb/ojp/OJP.xsd'; :) +declare variable $odir external := (); +declare variable $ofile external := (); +declare variable $domains external := (); +declare variable $custom external := (); +declare variable $forEachDomain as xs:boolean? external := false(); + +declare variable $uri external := (); (: '/projects/sbb/ojp/OJP.xsd'; :) +declare variable $skipAnno as xs:boolean? external := (); +declare variable $skipAtts as xs:string? external := (); +declare variable $keepAtts as xs:string? external := (); + + (: Default value of customization path: 'custom.xml' in the folder containing this module :) +declare variable $enames external := (); +declare variable $anames external := (); +declare variable $tnames external := (); +declare variable $gnames external := (); +declare variable $hnames external := (); +declare variable $ens external := (); +declare variable $ans external := (); +declare variable $tns external := (); +declare variable $gns external := (); +declare variable $hns external := (); +declare variable $global as xs:boolean external := true(); +declare variable $edescReport external := (); +declare variable $edescReportDir external := (); +declare variable $activeDomains external := (); +declare variable $debugDir external := (); +declare variable $debugFilter external := (); + +(: If no name filter is used: set default name filters :) +let $nonames := empty(($enames, $anames, $tnames, $gnames, $hnames)) +let $enames := ('*'[$nonames], $enames)[1] +let $anames := ('*'[$nonames], $anames)[1] +let $tnames := ('*'[$nonames], $tnames)[1] +let $gnames := ('*'[$nonames], $gnames)[1] +let $hnames := ('*'[$nonames], $hnames)[1] + +let $activeDomains := $activeDomains ! tokenize(.) +let $dirNorm := $dir ! u:normalizeUri(., ()) +let $odirNorm := $odir ! u:normalizeUri(., ()) +let $customNorm := $custom ! u:normalizeUri(., ()) +let $domainType := $domains +let $preliminaryOptions := + map{ + 'dir': $dirNorm, + 'odir': $odirNorm, + 'domains': $domainType, + 'activeDomains': $activeDomains + } +let $uris := + if ($dir) then file:descendants($dirNorm)[ends-with(., '.xsd')] + [not(file:name(.) = $fnamesExcluded)] + [not( + some $dname in tokenize($dnamesExcluded) satisfies + let $regex := u:literalToRegex($dname) + return matches(., '[/\\]'||$regex||'[/\\]', 'i'))] + else $uri +let $_DEBUG := trace(($dnamesExcluded, '-')[1], '*** Dnames excluded: ') +let $_DEBUG := trace(count($uris), '*** Count(input XSDs): ') +(: let $_DEBUG := trace($uris, '### URI: ') :) +let $schemas := sr:resolveSchemas($uris) => u:addLocalTypeIds() +let $schemaDict := map:merge($schemas/map:entry(base-uri(.) ! u:normalizeUri(., ()), .)) +let $customElem := cu:compileCustom($customNorm, $schemas, $preliminaryOptions) +let $domainsElem := $customElem//domains +let $ofileNorm := if (not($ofile)) then () else + let $fileName := $ofile ! file:name(.) + return string-join(($odirNorm, $report, $fileName), '/') +let $nsmap := ns:getTnsPrefixMap($schemas, $customElem) +(: skipAnno - default dependent on report type :) +let $skipAnno := + if ($skipAnno) then $skipAnno + else if ($report eq 'contab') then false() + else false() + +let $origReportType := $report +let $reportType := if ($report eq 'tree') then 'edesc' else $report +(: Folder containing intermediate edesc reports :) +let $edescReportDirDynamic := + if ($edescReportDir) then () + else if ($reportType ne 'contab') then () + else $odirNorm||'/edesc' +let $options := map{'skipAnno': $skipAnno, + 'skipAtts': $skipAtts, + 'keepAtts': $keepAtts, + 'custom': $customElem, + 'forEachDomain': $forEachDomain, + 'domains': $domainsElem, + 'domainType': $domainType, + 'schemas': $schemaDict, + 'nsmap': $nsmap, + 'dir': $dirNorm, + 'odir': $odirNorm, + 'ofile': $ofileNorm, + 'reportType': $reportType, + 'edescReport': $edescReport, + 'edescReportDir': $edescReportDir, + 'edescReportDirDynamic': $edescReportDirDynamic, + 'withEnumDict': false(), + 'deepResolve': $origReportType eq 'tree' + } +let $options := dg:SET_DEBUG_OPTIONS($debugDir, $debugFilter, $options) +(: Use debugFilter custom=yes,domains=yes in order to get downloads of the + : compiled custom file and the compiled domains :) +let $_WDEBUG := dg:WRITE_FILE($domainsElem, 'DOMAINS.xml', 'domains', 'yes', $options) +let $_WDEBUG := dg:WRITE_FILE($customElem, 'CUSTOM.xml', 'custom', 'yes', $options) +let $_CRDIR := ( + if (not($odirNorm)) then () + else if (file:exists($odirNorm)) then() + else file:create-dir($odirNorm), + if (not($ofileNorm)) then () + else + let $ofileDir := $ofileNorm ! fu:getParentPath(.) + return + if (file:exists($ofileDir)) then() + else file:create-dir($ofileDir) +) +let $_COPY := fu:copyCssFile($options) +let $_CHECK := ci:checkInput($reportType, $dir, $xsd, $odir, $ofile, $domains, $custom) + +let $reportDoc := cr:reportComps($reportType, + $enames, $anames, $tnames, $gnames, $hnames, + $ens, $ans, $tns, $gns, $hns, + $global, $schemas, $options) +return $reportDoc + + diff --git a/docs/generated/asciidoc.css b/docs/generated/asciidoc.css index ac9f43a90..49605ad1a 100644 --- a/docs/generated/asciidoc.css +++ b/docs/generated/asciidoc.css @@ -1,20 +1,23 @@ -/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ -/* Remove comment around @import statement below when using as a custom stylesheet */ -/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ -article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} -audio,canvas,video{display:inline-block} -audio:not([controls]){display:none;height:0} -[hidden],template{display:none} -script{display:none!important} -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} -a{background:transparent} +.announceBase {color:purple; background:#FFFDED; font-family: Montserrat, serif;} +.darkbrown {color:Maroon;} +.anno-text {color:Maroon;} +.monospace { font-family: Courier New, serif;} +.dir {font-size: 70%; color: #A0A0A0; font-family: Montserrat, serif;} +.tocsubtitle {font-size: 110%; font-style: italic;} + +/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */ +/* Uncomment the following line when using as a custom stylesheet */ +/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */ +html{font-family:sans-serif;-webkit-text-size-adjust:100%} +a{background:none} a:focus{outline:thin dotted} a:active,a:hover{outline:0} h1{font-size:2em;margin:.67em 0} -abbr[title]{border-bottom:1px dotted} b,strong{font-weight:bold} +abbr{font-size:.9em} +abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none} dfn{font-style:italic} -hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} +hr{height:0} mark{background:#ff0;color:#000} code,kbd,pre,samp{font-family:monospace;font-size:1em} pre{white-space:pre-wrap} @@ -26,22 +29,22 @@ sub{bottom:-.25em} img{border:0} svg:not(:root){overflow:hidden} figure{margin:0} +audio,video{display:inline-block} +audio:not([controls]){display:none;height:0} fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} legend{border:0;padding:0} button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} button,input{line-height:normal} button,select{text-transform:none} -button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} +button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer} button[disabled],html input[disabled]{cursor:default} -input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} -input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box} -input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none} +input[type=checkbox],input[type=radio]{padding:0} button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} textarea{overflow:auto;vertical-align:top} table{border-collapse:collapse;border-spacing:0} -*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} +*,::before,::after{box-sizing:border-box} html,body{font-size:100%} -body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} +body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} a:hover{cursor:pointer} img,object,embed{max-width:100%;height:auto} object,embed{height:100%} @@ -56,15 +59,12 @@ img{-ms-interpolation-mode:bicubic} img,object,svg{display:inline-block;vertical-align:middle} textarea{height:auto;min-height:50px} select{width:100%} -.center{margin-left:auto;margin-right:auto} -.spread{width:100%} -p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6} .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} -div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} +div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0} a{color:#2156a5;text-decoration:underline;line-height:inherit} a:hover,a:focus{color:#1d4b8f} -a img{border:none} -p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} +a img{border:0} +p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} p aside{font-size:.875em;line-height:1.35;font-style:italic} h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} @@ -73,51 +73,52 @@ h2{font-size:1.6875em} h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} h4,h5{font-size:1.125em} h6{font-size:1em} -hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} +hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em} em,i{font-style:italic;line-height:inherit} strong,b{font-weight:bold;line-height:inherit} small{font-size:60%;line-height:inherit} code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} -ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} +ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} ul,ol{margin-left:1.5em} -ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} -ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} -ul.square{list-style-type:square} +ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0} ul.circle{list-style-type:circle} ul.disc{list-style-type:disc} +ul.square{list-style-type:square} +ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit} ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} dl dt{margin-bottom:.3125em;font-weight:bold} dl dd{margin-bottom:1.25em} -abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} -abbr{text-transform:none} blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} -blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} -blockquote cite:before{content:"\2014 \0020"} -blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} -@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} -h1{font-size:2.75em} -h2{font-size:2.3125em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} -h4{font-size:1.4375em}} -table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} -table thead,table tfoot{background:#f7f8f7;font-weight:bold} +@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} + h1{font-size:2.75em} + h2{font-size:2.3125em} + h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} + h4{font-size:1.4375em}} +table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal} +table thead,table tfoot{background:#f7f8f7} table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} -table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} -table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} +table tr.even,table tr.alt{background:#f8f8f7} +table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6} h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} -.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table} -.clearfix:after,.float-group:after{clear:both} -*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} -*:not(pre)>code.nobreak{word-wrap:normal} -*:not(pre)>code.nowrap{white-space:nowrap} -pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} +.center{margin-left:auto;margin-right:auto} +.stretch{width:100%} +.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} +.clearfix::after,.float-group::after{clear:both} +:not(pre).nobreak{word-wrap:normal} +:not(pre).nowrap{white-space:nowrap} +:not(pre).pre-wrap{white-space:pre-wrap} +:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed} +pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed} +pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit} +pre>code{display:block} +pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal} em em{font-style:normal} strong strong{font-weight:400} .keyseq{color:rgba(51,51,51,.8)} -kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} +kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} .keyseq kbd:first-child{margin-left:0} .keyseq kbd:last-child{margin-right:0} .menuseq,.menuref{color:#000} @@ -125,29 +126,29 @@ kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-bl .menuseq{word-spacing:-.02em} .menuseq b.caret{font-size:1.25em;line-height:.8} .menuseq i.caret{font-weight:bold;text-align:center;width:.45em} -b.button:before,b.button:after{position:relative;top:-1px;font-weight:400} -b.button:before{content:"[";padding:0 3px 0 2px} -b.button:after{content:"]";padding:0 2px 0 3px} +b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} +b.button::before{content:"[";padding:0 3px 0 2px} +b.button::after{content:"]";padding:0 2px 0 3px} p a>code:hover{color:rgba(0,0,0,.9)} -#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} -#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table} -#header:after,#content:after,#footnotes:after,#footer:after{clear:both} +#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} +#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} +#header::after,#content::after,#footnotes::after,#footer::after{clear:both} #content{margin-top:1.25em} -#content:before{content:none} +#content::before{content:none} #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} -#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8} -#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px} -#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} +#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf} +#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px} +#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap} #header .details span:first-child{margin-left:-.125em} #header .details span.email a{color:rgba(0,0,0,.85)} #header .details br{display:none} -#header .details br+span:before{content:"\00a0\2013\00a0"} -#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} -#header .details br+span#revremark:before{content:"\00a0|\00a0"} +#header .details br+span::before{content:"\00a0\2013\00a0"} +#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} +#header .details br+span#revremark::before{content:"\00a0|\00a0"} #header #revnumber{text-transform:capitalize} -#header #revnumber:after{content:"\00a0"} -#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} -#toc{border-bottom:1px solid #efefed;padding-bottom:.5em} +#header #revnumber::after{content:"\00a0"} +#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} +#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em} #toc>ul{margin-left:.125em} #toc ul.sectlevel0>li>a{font-style:italic} #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} @@ -156,107 +157,118 @@ p a>code:hover{color:rgba(0,0,0,.9)} #toc a{text-decoration:none} #toc a:active{text-decoration:underline} #toctitle{color:#7a2518;font-size:1.2em} -@media only screen and (min-width:768px){#toctitle{font-size:1.375em} -body.toc2{padding-left:15em;padding-right:0} -#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} -#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} -#toc.toc2>ul{font-size:.9em;margin-bottom:0} -#toc.toc2 ul ul{margin-left:0;padding-left:1em} -#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} -body.toc2.toc-right{padding-left:0;padding-right:15em} -body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}} -@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} -#toc.toc2{width:20em} -#toc.toc2 #toctitle{font-size:1.375em} -#toc.toc2>ul{font-size:.95em} -#toc.toc2 ul ul{padding-left:1.25em} -body.toc2.toc-right{padding-left:0;padding-right:20em}} -#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} +@media screen and (min-width:768px){#toctitle{font-size:1.375em} + body.toc2{padding-left:15em;padding-right:0} + #toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} + #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} + #toc.toc2>ul{font-size:.9em;margin-bottom:0} + #toc.toc2 ul ul{margin-left:0;padding-left:1em} + #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} + body.toc2.toc-right{padding-left:0;padding-right:15em} + body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}} +@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} + #toc.toc2{width:20em} + #toc.toc2 #toctitle{font-size:1.375em} + #toc.toc2>ul{font-size:.95em} + #toc.toc2 ul ul{padding-left:1.25em} + body.toc2.toc-right{padding-left:0;padding-right:20em}} +#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px} #content #toc>:first-child{margin-top:0} #content #toc>:last-child{margin-bottom:0} -#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} -#footer-text{color:rgba(255,255,255,.8);line-height:1.44} +#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em} +#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44} +#content{margin-bottom:.625em} .sect1{padding-bottom:.625em} -@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}} -.sect1+.sect1{border-top:1px solid #efefed} +@media screen and (min-width:768px){#content{margin-bottom:1.25em} + .sect1{padding-bottom:1.25em}} +.sect1:last-child{padding-bottom:0} +.sect1+.sect1{border-top:1px solid #e7e7e9} #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} -#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} +#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} -.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} +details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} +details{margin-left:1.25rem} +details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent} +details>summary::-webkit-details-marker{display:none} +details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)} +details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)} +details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem} .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} -table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0} -.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)} -table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit} +table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} +.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} .admonitionblock>table td.icon{text-align:center;width:80px} -.admonitionblock>table td.icon img{max-width:initial} +.admonitionblock>table td.icon img{max-width:none} .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} -.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)} +.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere} .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} -.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} -.exampleblock>.content>:first-child{margin-top:0} -.exampleblock>.content>:last-child{margin-bottom:0} -.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} -.sidebarblock>:first-child{margin-top:0} -.sidebarblock>:last-child{margin-bottom:0} +.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px} +.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px} .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} -.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} -.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} -.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} -.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em} -.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal} -@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} -@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} -.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} +.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0} +.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} +.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em} +@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}} +@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}} +.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8} +.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)} +.listingblock>.content{position:relative} +.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5} +.listingblock:hover code[data-lang]::before{display:block} +.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5} +.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} .listingblock pre.highlightjs{padding:0} -.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} +.listingblock pre.highlightjs>code{padding:1em;border-radius:4px} .listingblock pre.prettyprint{border-width:0} -.listingblock>.content{position:relative} -.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} -.listingblock:hover code[data-lang]:before{display:block} -.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999} -.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"} -table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} -table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} -table.pyhltable td.code{padding-left:.75em;padding-right:0} -pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8} -pre.pygments .lineno{display:inline-block;margin-right:.25em} -table.pyhltable .linenodiv{background:none!important;padding-right:0!important} +.prettyprint{background:#f7f7f8} +pre.prettyprint .linenums{line-height:1.45;margin-left:2em} +pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0} +pre.prettyprint li code[data-lang]::before{opacity:1} +pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none} +table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none} +table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal} +table.linenotable td.code{padding-left:.75em} +table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +pre.pygments span.linenos{display:inline-block;margin-right:.75em} .quoteblock{margin:0 1em 1.25em 1.5em;display:table} -.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} -.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} +.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em} +.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} .quoteblock blockquote{margin:0;padding:0;border:0} -.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} +.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} -.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right} -.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)} -.quoteblock .quoteblock blockquote{padding:0 0 0 .75em} -.quoteblock .quoteblock blockquote:before{display:none} -.verseblock{margin:0 1em 1.25em 1em} -.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} +.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right} +.verseblock{margin:0 1em 1.25em} +.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} .verseblock pre strong{font-weight:400} .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} .quoteblock .attribution br,.verseblock .attribution br{display:none} .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} -.quoteblock.abstract{margin:0 0 1.25em 0;display:block} -.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0} -.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none} -table.tableblock{max-width:100%;border-collapse:separate} -table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0} +.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none} +.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0} +.quoteblock.abstract{margin:0 1em 1.25em;display:block} +.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} +.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf} +.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0} +.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem} +.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0} +p.tableblock:last-child{margin-bottom:0} +td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere} +td.tableblock>.content>:last-child{margin-bottom:-1.25em} table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} -table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0} -table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0} -table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0} -table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0} -table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0} -table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0} -table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0} +table.grid-all>*>tr>*{border-width:1px} +table.grid-cols>*>tr>*{border-width:0 1px} +table.grid-rows>*>tr>*{border-width:1px 0} table.frame-all{border-width:1px} +table.frame-ends{border-width:1px 0} table.frame-sides{border-width:0 1px} -table.frame-topbot{border-width:1px 0} +table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0} +table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0} +table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0} +table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0} +table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7} th.halign-left,td.halign-left{text-align:left} th.halign-right,td.halign-right{text-align:right} th.halign-center,td.halign-center{text-align:center} @@ -264,25 +276,24 @@ th.valign-top,td.valign-top{vertical-align:top} th.valign-bottom,td.valign-bottom{vertical-align:bottom} th.valign-middle,td.valign-middle{vertical-align:middle} table thead th,table tfoot th{font-weight:bold} -tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} +tbody tr th{background:#f7f8f7} tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} p.tableblock>code:only-child{background:none;padding:0} p.tableblock{font-size:1em} -td>div.verse{white-space:pre} ol{margin-left:1.75em} ul li ol{margin-left:1.5em} dl dd{margin-left:1.125em} dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} -ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} +li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} ul.unstyled,ol.unstyled{margin-left:0} -ul.checklist{margin-left:.625em} -ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} -ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em} -ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden} -ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block} -ul.inline>li>*{display:block} +li>p:empty:only-child::before{content:"";display:inline-block} +ul.checklist>li>p:first-child{margin-left:-1em} +ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} +ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em} +ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} +ul.inline>li{margin-left:1.25em} .unstyled dl dt{font-weight:400;font-style:normal} ol.arabic{list-style-type:decimal} ol.decimal{list-style-type:decimal-leading-zero} @@ -295,13 +306,14 @@ ol.lowergreek{list-style-type:lower-greek} .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} td.hdlist1{font-weight:bold;padding-bottom:1.25em} +td.hdlist2{word-wrap:anywhere} .literalblock+.colist,.listingblock+.colist{margin-top:-.5em} -.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top} -.colist>table tr>td:first-of-type img{max-width:initial} -.colist>table tr>td:last-of-type{padding:.25em 0} -.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} -.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0} -.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em} +.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} +.colist td:not([class]):first-child img{max-width:none} +.colist td:not([class]):last-child{padding:.25em 0} +.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd} +.imageblock.left{margin:.25em .625em 1.25em 0} +.imageblock.right{margin:.25em 0 1.25em .625em} .imageblock>.title{margin-bottom:0} .imageblock.thumb,.imageblock.th{border-width:6px} .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} @@ -314,13 +326,11 @@ sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:sup sup.footnote a,sup.footnoteref a{text-decoration:none} sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} -#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0} -#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em} -#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none} +#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} +#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} +#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} #footnotes .footnote:last-of-type{margin-bottom:0} #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} -.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} -.gist .file-data>table td.line-data{width:99%} div.unbreakable{page-break-inside:avoid} .big{font-size:larger} .small{font-size:smaller} @@ -328,88 +338,93 @@ div.unbreakable{page-break-inside:avoid} .overline{text-decoration:overline} .line-through{text-decoration:line-through} .aqua{color:#00bfbf} -.aqua-background{background-color:#00fafa} +.aqua-background{background:#00fafa} .black{color:#000} -.black-background{background-color:#000} +.black-background{background:#000} .blue{color:#0000bf} -.blue-background{background-color:#0000fa} +.blue-background{background:#0000fa} .fuchsia{color:#bf00bf} -.fuchsia-background{background-color:#fa00fa} +.fuchsia-background{background:#fa00fa} .gray{color:#606060} -.gray-background{background-color:#7d7d7d} +.gray-background{background:#7d7d7d} .green{color:#006000} -.green-background{background-color:#007d00} +.green-background{background:#007d00} .lime{color:#00bf00} -.lime-background{background-color:#00fa00} +.lime-background{background:#00fa00} .maroon{color:#600000} -.maroon-background{background-color:#7d0000} +.maroon-background{background:#7d0000} .navy{color:#000060} -.navy-background{background-color:#00007d} +.navy-background{background:#00007d} .olive{color:#606000} -.olive-background{background-color:#7d7d00} +.olive-background{background:#7d7d00} .purple{color:#600060} -.purple-background{background-color:#7d007d} +.purple-background{background:#7d007d} .red{color:#bf0000} -.red-background{background-color:#fa0000} +.red-background{background:#fa0000} .silver{color:#909090} -.silver-background{background-color:#bcbcbc} +.silver-background{background:#bcbcbc} .teal{color:#006060} -.teal-background{background-color:#007d7d} +.teal-background{background:#007d7d} .white{color:#bfbfbf} -.white-background{background-color:#fafafa} +.white-background{background:#fafafa} .yellow{color:#bfbf00} -.yellow-background{background-color:#fafa00} +.yellow-background{background:#fafa00} span.icon>.fa{cursor:default} a span.icon>.fa{cursor:inherit} .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} -.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c} -.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} -.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900} -.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400} -.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000} -.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} +.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} +.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} +.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} +.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} +.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} +.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} .conum[data-value] *{color:#fff!important} .conum[data-value]+b{display:none} -.conum[data-value]:after{content:attr(data-value)} +.conum[data-value]::after{content:attr(data-value)} pre .conum[data-value]{position:relative;top:-.125em} b.conum *{color:inherit!important} .conum:not([data-value]):empty{display:none} dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} -h1,h2,p,td.content,span.alt{letter-spacing:-.01em} +h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em} p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} -p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} +p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem} p{margin-bottom:1.25rem} .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} -.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} +.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc} .print-only{display:none!important} -@media print{@page{margin:1.25cm .75cm} -*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} -a{color:inherit!important;text-decoration:underline!important} -a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} -a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} -abbr[title]:after{content:" (" attr(title) ")"} -pre,blockquote,tr,img,object,svg{page-break-inside:avoid} -thead{display:table-header-group} -svg{max-width:100%} -p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} -h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} -#toc,.sidebarblock,.exampleblock>.content{background:none!important} -#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important} -.sect1{padding-bottom:0!important} -.sect1+.sect1{border:0!important} -#header>h1:first-child{margin-top:1.25rem} -body.book #header{text-align:center} -body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0} -body.book #header .details{border:0!important;display:block;padding:0!important} -body.book #header .details span:first-child{margin-left:0!important} -body.book #header .details br{display:block} -body.book #header .details br+span:before{content:none!important} -body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} -body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} -.listingblock code[data-lang]:before{display:block} -#footer{background:none!important;padding:0 .9375em} -#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em} -.hide-on-print{display:none!important} -.print-only{display:block!important} -.hide-for-print{display:none!important} -.show-for-print{display:inherit!important}} +@page{margin:1.25cm .75cm} +@media print{*{box-shadow:none!important;text-shadow:none!important} + html{font-size:80%} + a{color:inherit!important;text-decoration:underline!important} + a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} + a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} + abbr[title]{border-bottom:1px dotted} + abbr[title]::after{content:" (" attr(title) ")"} + pre,blockquote,tr,img,object,svg{page-break-inside:avoid} + thead{display:table-header-group} + svg{max-width:100%} + p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} + h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} + #header,#content,#footnotes,#footer{max-width:none} + #toc,.sidebarblock,.exampleblock>.content{background:none!important} + #toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important} + body.book #header{text-align:center} + body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} + body.book #header .details{border:0!important;display:block;padding:0!important} + body.book #header .details span:first-child{margin-left:0!important} + body.book #header .details br{display:block} + body.book #header .details br+span::before{content:none!important} + body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} + body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} + .listingblock code[data-lang]::before{display:block} + #footer{padding:0 .9375em} + .hide-on-print{display:none!important} + .print-only{display:block!important} + .hide-for-print{display:none!important} + .show-for-print{display:inherit!important}} +@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem} + .sect1{padding:0!important} + .sect1+.sect1{border:0} + #footer{background:none} + #footer-text{color:rgba(0,0,0,.6);font-size:.9em}} +@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} diff --git a/docs/ojp-base.xsl b/docs/ojp-base.xsl deleted file mode 100644 index 612c73158..000000000 --- a/docs/ojp-base.xsl +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - : - / - - - - - Element has no 'name' attribute! - - - - - - - - - - - - - - - - - - - - - - - - - - Element has no 'name' attribute! - - - - - - - .xsd - - - - diff --git a/docs/ojp-prep-to-html-with-toc.xsl b/docs/ojp-prep-to-html-with-toc.xsl deleted file mode 100644 index a4936e874..000000000 --- a/docs/ojp-prep-to-html-with-toc.xsl +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - -
  • -
      - -
    -
  • -
    - - -
  • -
    - - -
  • Simple type definitions
  • -
    - - - - . - - - - - - . - - - - - - - - - - - - - - - - - - - - - - - - Simple type definitions - - -
    - diff --git a/docs/ojp-prep-to-html.xsl b/docs/ojp-prep-to-html.xsl deleted file mode 100644 index d06228b7d..000000000 --- a/docs/ojp-prep-to-html.xsl +++ /dev/null @@ -1,518 +0,0 @@ - - - - - - - - - - - - - : - / - - - - - - - - - - - - - - <!DOCTYPE html> - - - OJP - Open API for distributed Journey Planning - - - - - - - - - - -
    - -
    - - - -
    - - - - - - - - - - - - - - - - - Simple type definitions - - - - - Invalid element for mode='title': - - - - - - - - - - - ========================================================= schema -
    - -

    - - - -

    -
    - -
    -
    -
    - - - - - - - - - - - - - -
    -

    - -

    -
    - - - - - - - - - -
    -
    -
    -
    - - - - - -

    - -

    - - -

    - - - - - - | - - - - - - - - -

    - - -

    - -

    - - -
    - - - - - - - - - - - - - - - - - - - - - ======================================= chapter -
    - -

    - -

    -
    - -
    -
    -
    - - - - - - - - - - - - - - - - -
    -
    - - - ======= type-description - - -

    - -

    - - -

    - - - - ( - - - - ) - - -

    - - -

    - -

    - - -
    - - - ======= line - - -

    - -

    - - -
    - - - ======= row - - - - - - - - - - - - - - - - - - - - - - - rowspan: : - - - - - - - - - - - - - - - - - - - -

    - - - - -

    - -

    - -
    - - - - - - - - - - - - - -

    - -

    - - -

    - -

    - - -

    - -

    - - -

    - -

    - - -
    - - - - - - - - - - - - - - - - - - - - optional, single - optional, multiple - mandatory, single - mandatory, at least one - optional, single, part of a choice - optional, multiple, part of a choice - mandatory, single, part of a choice - mandatory, at least one, part of a choice - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Element not implemented, yet: - - -
    - diff --git a/docs/ojp-to-prepdoc.xsl b/docs/ojp-to-prepdoc.xsl deleted file mode 100644 index d541cb1c6..000000000 --- a/docs/ojp-to-prepdoc.xsl +++ /dev/null @@ -1,736 +0,0 @@ - - - - - - - - - - - - - a - b - c - d - e - f - g - h - i - j - k - l - m - n - o - p - q - r - s - t - u - v - w - x - y - z - - - - - - - - - - 1 - - - - - * - - 1 - - - - - - - bold - - - - - - - : - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - - - - Unhandled case for - - - - - - - - - - - - - - - - - - - - - - - Unhandled case for mode 'type' on : - - - - -

    - Fixed value: " - - " -

    -
    - - - - - - - - - - -
    - - - Unhandled case for mode 'documentation' on : - - - - - - - - - output-name-ref: name is empty! - - - - - - - - - - - - - - - - - - - - - - - - - →‍ - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - bold - - - - - - - - - bold - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    - -

    -
    - - - - - - - element - - - <xsl:text>The toplevel element </xsl:text> - <code><xsl:value-of select="@name"/></code> - - - - - - - - - - - - -
    -
    -
    - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Documentation is not allowed on xs:sequence! Context: - - - - The element contains - - - only one element: - - - a - sequence - of the following elements: - - - - - - - - - - - - - - - - xs:choice with just one child! Context: - - - - - - - - - - The element contains only one element: - - - - - - - - - - - - - - - - Documentation is not allowed on xs:choice! Context: - - - - - The element contains one of the following elements: - Then, the element contains one of the following elements: - - - - - - - - - - - - - - - group - - - <xsl:text>The </xsl:text> - <code><xsl:value-of select="@name"/></code> - <xsl:text> group</xsl:text> - - - - - - - - - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - Group ──────┐ - - - - - Group ──────┘ - - - Group could not be resolved: → - Group could not be resolved: → - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Unnamed complexTypes are not allowed inside complexTypes! Context: - - - - - - - - - - - - - - - - - complexType - - The complex type ` - - ` - - - - - - - - - - - - - - <xsl:text>The complex type </xsl:text> - <code><xsl:value-of select="@name"/></code> - - - - - - - - - - - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Proper documentation rules for simpleType not in place, yet! - - - - - | | ` - - ` - | - - - - - - - - - - - - 0 - -1 - 1 - - - - - - @ - - - - - - - - - - - - - - - - ============================================================= Schema file === - - - - - - - - - <!-- All documentation on the schema itself is suppressed, as it is used as the section title --> - <xsl:value-of select="xs:annotation/xs:documentation"/> - - - - - - - - - - - - - - - - - - - - -
    - - diff --git a/docs/schema-collection.xml b/docs/schema-collection.xml deleted file mode 100644 index 6b2cc43e1..000000000 --- a/docs/schema-collection.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/theme.yml b/docs/theme.yml deleted file mode 100644 index 2aef8b384..000000000 --- a/docs/theme.yml +++ /dev/null @@ -1,272 +0,0 @@ -font: - catalog: - # Noto Serif supports Latin, Latin-1 Supplement, Latin Extended-A, Greek, Cyrillic, Vietnamese & an assortment of symbols - Noto Serif: - normal: notoserif-regular-subset.ttf - bold: notoserif-bold-subset.ttf - italic: notoserif-italic-subset.ttf - bold_italic: notoserif-bold_italic-subset.ttf - # M+ 1mn supports ASCII and the circled numbers used for conums - M+ 1mn: - normal: mplus1mn-regular-ascii-conums.ttf - bold: mplus1mn-bold-ascii.ttf - italic: mplus1mn-italic-ascii.ttf - bold_italic: mplus1mn-bold_italic-ascii.ttf - # M+ 1p supports Latin, Latin-1 Supplement, Latin Extended, Greek, Cyrillic, Vietnamese, Japanese & an assortment of symbols - # It also provides arrows for ->, <-, => and <= replacements in case these glyphs are missing from font - M+ 1p Fallback: - normal: mplus1p-regular-fallback.ttf - bold: mplus1p-regular-fallback.ttf - italic: mplus1p-regular-fallback.ttf - bold_italic: mplus1p-regular-fallback.ttf - fallbacks: - - M+ 1p Fallback -page: - background_color: ffffff - layout: portrait - # top, right, bottom, left - margin: [ 2.5cm, 2cm, 2.5cm, 3cm ] - # margin_inner and margin_outer keys are used for recto/verso print margins when media=press - margin_inner: 2cm - margin_outer: 3cm - size: A4 -base: - align: justify - # color as hex string (leading # is optional) - font_color: 333333 - # color as RGB array - #font_color: [51, 51, 51] - # color as CMYK array (approximated) - #font_color: [0, 0, 0, 0.92] - #font_color: [0, 0, 0, 92%] - font_family: Noto Serif - # choose one of these font_size/line_height_length combinations - #font_size: 14 - #line_height_length: 20 - #font_size: 11.25 - #line_height_length: 18 - #font_size: 11.2 - #line_height_length: 16 - font_size: 10.5 - #line_height_length: 15 - # correct line height for Noto Serif metrics - line_height_length: 12 - #font_size: 11.25 - #line_height_length: 18 - line_height: $base_line_height_length / $base_font_size - font_size_large: round($base_font_size * 1.25) - font_size_small: round($base_font_size * 0.85) - font_size_min: $base_font_size * 0.75 - font_style: normal - border_color: eeeeee - border_radius: 4 - border_width: 0.5 -# FIXME vertical_rhythm is weird; we should think in terms of ems -#vertical_rhythm: $base_line_height_length * 2 / 3 -# correct line height for Noto Serif metrics (comes with built-in line height) -vertical_rhythm: $base_line_height_length -horizontal_rhythm: $base_line_height_length -# QUESTION should vertical_spacing be block_spacing instead? -vertical_spacing: $vertical_rhythm -link: - font_color: 428bca -# literal is currently used for inline monospaced in prose and table cells -literal: - font_color: b12146 - font_family: M+ 1mn -menu_caret_content: " \u203a " -heading: - align: left - #font_color: 181818 - font_color: $base_font_color - font_family: $base_font_family - font_style: bold - # h1 is used for part titles (book doctype only) - h1_font_size: floor($base_font_size * 2.6) - # h2 is used for chapter titles (book doctype only) - h2_font_size: floor($base_font_size * 2.15) - h3_font_size: round($base_font_size * 1.7) - h4_font_size: $base_font_size_large - h5_font_size: $base_font_size - h6_font_size: $base_font_size_small - #line_height: 1.4 - # correct line height for Noto Serif metrics (comes with built-in line height) - line_height: 1 - margin_top: $vertical_rhythm * 0.4 - margin_bottom: $vertical_rhythm * 0.9 -title_page: - align: right - logo: - top: 10% - title: - top: 55% - font_size: $heading_h1_font_size - font_color: 999999 - line_height: 0.9 - subtitle: - font_size: $heading_h3_font_size - font_style: bold_italic - line_height: 1 - authors: - margin_top: $base_font_size * 1.25 - font_size: $base_font_size_large - font_color: 181818 - revision: - margin_top: $base_font_size * 1.25 -block: - margin_top: 0 - margin_bottom: $vertical_rhythm -caption: - align: left - font_style: italic - # FIXME perhaps set line_height instead of / in addition to margins? - margin_inside: $vertical_rhythm / 3 - #margin_inside: $vertical_rhythm / 4 - margin_outside: 0 -lead: - font_size: $base_font_size_large - line_height: 1.4 -abstract: - font_color: 5c6266 - font_size: $lead_font_size - line_height: $lead_line_height - font_style: italic - first_line_font_style: bold -admonition: - border_color: $base_border_color - border_width: $base_border_width - padding: [ 0, $horizontal_rhythm, 0, $horizontal_rhythm ] -# icon: -# tip: -# name: fa-lightbulb-o -# stroke_color: 111111 -# size: 24 -blockquote: - font_color: $base_font_color - font_size: $base_font_size_large - border_color: $base_border_color - border_width: 5 - padding: [ 0, $horizontal_rhythm, $block_margin_bottom * -0.75, $horizontal_rhythm + $blockquote_border_width / 2 ] - cite_font_size: $base_font_size_small - cite_font_color: 999999 -# code is used for source blocks (perhaps change to source or listing?) -code: - font_color: $base_font_color - font_family: $literal_font_family - font_size: ceil($base_font_size) - padding: $code_font_size - line_height: 1.25 - background_color: f5f5f5 - border_color: cccccc - border_radius: $base_border_radius - border_width: 0.75 -conum: - font_family: M+ 1mn - font_color: $literal_font_color - font_size: $base_font_size - line_height: 4 / 3 -example: - border_color: $base_border_color - border_radius: $base_border_radius - border_width: 0.75 - background_color: transparent - # FIXME reenable margin bottom once margin collapsing is implemented - padding: [ $vertical_rhythm, $horizontal_rhythm, 0, $horizontal_rhythm ] -image: - align: left -prose: - margin_top: $block_margin_top - margin_bottom: $block_margin_bottom -sidebar: - border_color: $page_background_color - border_radius: $base_border_radius - border_width: $base_border_width - background_color: eeeeee - # FIXME reenable margin bottom once margin collapsing is implemented - padding: [ $vertical_rhythm, $vertical_rhythm * 1.25, 0, $vertical_rhythm * 1.25 ] - title: - align: center - font_color: $heading_font_color - font_family: $heading_font_family - font_size: $heading_h4_font_size - font_style: $heading_font_style -thematic_break: - border_color: $base_border_color - border_style: solid - border_width: $base_border_width - margin_top: $vertical_rhythm * 0.5 - margin_bottom: $vertical_rhythm * 1.5 -description_list: - term_font_style: italic - term_spacing: $vertical_rhythm / 4 - description_indent: $horizontal_rhythm * 1.25 -outline_list: - indent: $horizontal_rhythm * 1.5 - # NOTE item_spacing applies to list items that do not have complex content - item_spacing: $vertical_rhythm / 2 - #marker_font_color: 404040 -table: - background_color: $page_background_color - #head_background_color: - #head_font_color: $base_font_color - head_font_style: bold - even_row_background_color: f9f9f9 - #odd_row_background_color: - foot_background_color: f0f0f0 - border_color: dddddd - border_width: $base_border_width - # HACK accounting for line-height - cell_padding: [ 3, 3, 6, 3 ] -toc: - dot_leader_color: dddddd - #dot_leader_content: '. ' - indent: $horizontal_rhythm - line_height: 1.4 -# NOTE In addition to footer, header is also supported -footer: - font_size: $base_font_size_small - # NOTE if background_color is set, background and border will span width of page - border_color: dddddd - border_width: 0.25 - height: $base_line_height_length * 4.5 - line_height: 1 - padding: [ $base_line_height_length / 2, 1, 0, 1 ] - vertical_align: top - #image_vertical_align: or - # additional attributes for content: - # * {page-count} - # * {page-number} - # * {document-title} - # * {document-subtitle} - # * {chapter-title} - # * {section-title} - # * {section-or-chapter-title} - recto: - #columns: "<50%,0%,>50%" - right: - content: '{page-number} of {page-count}' - #content: '{section-or-chapter-title} | {page-number}' - #content: '{document-title} | {page-number}' - center: - content: 'Version from {docdate}' - verso: - #columns: "<50%,0%,>50%" - left: - content: '{page-number} of {page-count}' - #content: '{page-number} | {chapter-title}' - center: - content: 'Version from {docdate}' -header: - font_size: $base_font_size_small - border_color: dddddd - border_width: 0.25 - height: $base_line_height_length * 4.5 - line_height: 1 - padding: [ $base_line_height_length / 2, 1, 0, 1 ] - vertical_align: bottom - recto: - center: - content: '{document-title}' - verso: - center: - content: '{document-title}' diff --git a/docs/validate-schema-conventions.sh b/docs/validate-schema-conventions.sh deleted file mode 100755 index 6fd45f1ce..000000000 --- a/docs/validate-schema-conventions.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# Validate the OJP Schema on adherence to design and documentation conventions -# -# You need the binary `xsltproc` -# apt-get install xsltproc - -# The -e flag causes the script to exit as soon as one command returns a non-zero exit code -set -e - -echo "Validating OJP Schema conventions ..." - -base_dir="$(dirname "${0}")/.." -xsl_dir=$base_dir/docs - -# Run the checks in the checker stylesheet -saved_output=$(xsltproc --xinclude "${xsl_dir}"/check-ojp-schemas.xsl "${xsl_dir}"/schema-collection.xml 2>&1) -echo -e "$saved_output" -errors=$(echo "$saved_output" | awk '/ERROR/') -if [ -n "$errors" ] -then - echo -e '\033[1;31mValidating OJP Schema conventions failed\033[0m' - exit 1 -else - echo -e '\033[0;32mValidating OJP Schema conventions succeeded\033[0m' -fi