Skip to content

Commit

Permalink
rename variable for better clarity
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentml committed Jul 13, 2022
1 parent 67f844b commit fd55700
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 49 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,50 +20,50 @@ Resolves the DOCTYPE declaration in an XML file using the XML Catalog. If the XM

Signature:

resolver:resolveDOCTYPE($xml as xs:string, $catfile as xs:string) as xs:string
resolver:resolveDOCTYPE($xml as xs:string, $catalog as xs:string) as xs:string

Parameters:

- $xml - XML document as a string
- $catfile - location of the XML Catalog file(s)
- $catalog - location of the XML Catalog file(s)

### resolveURI

Resolves a URI using the XML Catalog. If the URI matches an entry in the XML Catalog defined with a `uri`, `uriSuffix`, or `rewriteURI` element the URI will be resolved to the location specified in the catalog entry. If no match is found in the XML Catalog then the URI will be returned unchanged.

Signature:

resolver:resolveURI($uri as xs:string, $catfile as xs:string) as xs:string
resolver:resolveURI($uri as xs:string, $catalog as xs:string) as xs:string

Parameters:

- $uri - the URI to resolve
- $catfile - location of the XML Catalog file(s)
- $catalog - location of the XML Catalog file(s)

### parse-xml

Resolves the DOCTYPE declaration in an XML file using the XML Catalog and then parses the XML.

Signature:

resolver:parse-xml($xml as xs:string, $catfile as xs:string) as document-node()
resolver:parse-xml($xml as xs:string, $catalog as xs:string) as document-node()

Parameters:

- $xml - XML document as a string or a URI to an XML document
- $catfile - location of the XML Catalog file(s)
- $catalog - location of the XML Catalog file(s)

## XML Catalog File Location

The location of the XML Catalog file should be provided as an absolute file path. Multiple XML Catalog files can be used by providing a semicolon separated list of the file paths.

The location of the XML Catalog file can be written in an XQuery just like any other string.

let $catfile := "C:\schemas\catalog.xml"
let $catalog := "C:\schemas\catalog.xml"

The absolute path to the catalog file can be determined relative to an XQuery file. The [File module](https://docs.basex.org/wiki/File_Module) provides functions that can help with identifying an absolute file path, for example:

let $catfile := file:resolve-path('schemas/catalog.xml', file:base-dir())
let $catalog := file:resolve-path('schemas/catalog.xml', file:base-dir())

There are also several ways to configure the location of the XML Catalog file(s) using BaseX configuration, Java system properties, and environment variables. With all of these methods, the value should be a semicolon separated list of absolute file paths.

Expand All @@ -76,7 +76,7 @@ There are also several ways to configure the location of the XML Catalog file(s)
The following XQuery snippet can be used to get the location of the XML Catalog file(s) from any one of the above locations that has a value.

```xquery
let $catfile := head((
let $catalog := head((
db:option("catfile"),
proc:property("org.basex.catfile"),
proc:property("javax.xml.catalog.files"),
Expand All @@ -92,7 +92,7 @@ An XML Catalog file can import other XML Catalog file(s) using elements `nextCat
```xquery
import module namespace resolver = "xml-catalog-resolver" at "https://raw.githubusercontent.com/vincentml/xml-catalog-resolver/main/xml-catalog-resolver.xqm";
let $catfile := head((
let $catalog := head((
db:option("catfile"),
proc:property("org.basex.catfile"),
proc:property("javax.xml.catalog.files"),
Expand All @@ -102,7 +102,7 @@ let $catfile := head((
let $doc := "example.xml"
return resolver:parse-xml($doc, $catfile)
return resolver:parse-xml($doc, $catalog)
```

## Resources
Expand Down
76 changes: 38 additions & 38 deletions xml-catalog-resolver.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ declare variable $resolver:doctype_start := '(<!DOCTYPE' || $resolver:space || '
: URI expansion will be based on file paths relative to the XML Catalog file or
: the @xml:base attribute if present in the XML Catalog.
:
: @param $catfile Semicolon-separated list of XML catalog files. Absolute file path works best.
: @param $catalog Semicolon-separated list of XML catalog files. Absolute file path works best.
:
: @return Sequence of all entries from all XML Catalogs that were loaded.
:)
declare function resolver:catalogEntries($catfile as xs:string) as element()* {
for $cat in tokenize($catfile, ';\s*') return
let $catalog := (# db:dtd false #) (# db:intparse true #) { doc(file:resolve-path($cat)) }
declare function resolver:catalogEntries($catalog as xs:string) as element()* {
for $cat in tokenize($catalog, ';\s*') return
let $catxml := (# db:dtd false #) (# db:intparse true #) { doc(file:resolve-path($cat)) }
let $catparent := file:parent($cat)
for $e in $catalog//*
for $e in $catxml//*
let $base :=
if ($e/ancestor-or-self::catalog:*/@xml:base)
then ($e/ancestor-or-self::catalog:*/@xml:base)[last()]/string()
Expand Down Expand Up @@ -86,16 +86,16 @@ declare %private function resolver:regexEscapeString($string as xs:string) as xs
: No attempt has been made to skip text that looks like a DOCTYPE but isn't, such as a DOCTYPE that is inside a comment.
:
: @param $xml XML as a string
: @param $catfile Semicolon-separated list of XML catalog files. Absolute file path works best.
: @param $catalog Semicolon-separated list of XML catalog files. Absolute file path works best.
:
: @return XML string with DOCTYPE resolved using the XML Catalog. If no mapping is found then the string is returned unchanged.
:
: @see https://www.w3.org/TR/xml/#NT-doctypedecl
:)
declare function resolver:resolveDOCTYPE($xml as xs:string, $catfile as xs:string) as xs:string {
let $catalog := resolver:catalogEntries($catfile)
declare function resolver:resolveDOCTYPE($xml as xs:string, $catalog as xs:string) as xs:string {
let $cat := resolver:catalogEntries($catalog)

return fold-left($catalog, $xml, function($x, $c) {
return fold-left($cat, $xml, function($x, $c) {
typeswitch ($c)
case element(catalog:public) return
let $public := resolver:regexEscapeString($c/@publicId)
Expand Down Expand Up @@ -130,13 +130,13 @@ declare function resolver:resolveDOCTYPE($xml as xs:string, $catfile as xs:strin
: Resolve a URI using XML Catalog.
:
: @param $uri The URI to resolve
: @param $catfile Semicolon-separated list of XML catalog files. Absolute file path works best.
: @param $catalog Semicolon-separated list of XML catalog files. Absolute file path works best.
:
: @return The resolved URI. If no mapping is found in the XML Catalog the URI will be returned unchanged.
:)
declare function resolver:resolveURI($uri as xs:string, $catfile as xs:string) as xs:string {
let $catalog := resolver:catalogEntries($catfile)
return fold-left($catalog, $uri, function($x, $c) {
declare function resolver:resolveURI($uri as xs:string, $catalog as xs:string) as xs:string {
let $cat := resolver:catalogEntries($catalog)
return fold-left($cat, $uri, function($x, $c) {
typeswitch ($c)
case element(catalog:uri) return
if ($c/@name eq $uri) then string($c/@uri) else $x
Expand All @@ -157,14 +157,14 @@ declare function resolver:resolveURI($uri as xs:string, $catfile as xs:string) a
: Parse XML using XML Catalog
:
: @param $xml an XML string or file path to the XML file
: @param $catfile Semicolon-separated list of XML catalog files. Absolute file path works best.
: @param $catalog Semicolon-separated list of XML catalog files. Absolute file path works best.
:
: @return parsed XML document
:)
declare function resolver:parse-xml($xml as xs:string, $catfile as xs:string) as document-node() {
declare function resolver:parse-xml($xml as xs:string, $catalog as xs:string) as document-node() {
let $temp := file:create-temp-file('catalog-resolver', '.xml')
let $raw := if ($xml castable as xs:anyURI) then unparsed-text($xml) else $xml
let $resolved := resolver:resolveDOCTYPE($raw, $catfile)
let $resolved := resolver:resolveDOCTYPE($raw, $catalog)
return (
file:write-text($temp, $resolved),
(# db:dtd true #) (# db:intparse false #) (# db:chop false #) { doc($temp) },
Expand Down Expand Up @@ -201,9 +201,9 @@ declare %unit:test function resolver:test_regexEscapeString() {

declare %unit:test function resolver:test_catalogEntries() {
let $base := file:base-dir()
let $catfile := file:resolve-path("test/catalog1.xml", $base)
let $catalog := file:resolve-path("test/catalog1.xml", $base)
let $exampledtd := file:path-to-uri(file:resolve-path("test/example.dtd", $base))
let $entries := resolver:catalogEntries($catfile)
let $entries := resolver:catalogEntries($catalog)
return (
unit:assert-equals($entries[1], <catalog:system systemId="https://example.org/example.dtd" uri="{$exampledtd}"/>),
unit:assert-equals($entries[2], <catalog:systemSuffix systemIdSuffix="example.dtd" uri="{$exampledtd}"/>),
Expand All @@ -224,67 +224,67 @@ declare %unit:test function resolver:test_catalogEntries() {

declare %unit:test function resolver:test_resolveDOCTYPE() {
let $base := file:base-dir()
let $catfile := file:resolve-path("test/catalog1.xml", $base)
let $catalog := file:resolve-path("test/catalog1.xml", $base)
let $exampledtd := file:path-to-uri(file:resolve-path("test/example.dtd", $base))
return (
let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC "-//EXAMPLE//DTD v1//EN" "not-mapped"><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC "-//EXAMPLE//DTD v1//EN" "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'public'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC ''-//EXAMPLE//DTD v1//EN'' ''not-mapped''><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC ''-//EXAMPLE//DTD v1//EN'' "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'public'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC "-//EXAMPLE//not mapped//EN" "https://example.org/example.dtd"><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC "-//EXAMPLE//not mapped//EN" "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'system'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC ''-//EXAMPLE//not mapped//EN'' ''https://example.org/example.dtd''><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC ''-//EXAMPLE//not mapped//EN'' "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'system'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM "https://example.org/example.dtd"><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'system'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM ''https://example.org/example.dtd''><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'system'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC "-//EXAMPLE//not mapped//EN" "path/to/example.dtd"><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC "-//EXAMPLE//not mapped//EN" "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'systemSuffix'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC ''-//EXAMPLE//not mapped//EN'' ''path/to/example.dtd''><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC ''-//EXAMPLE//not mapped//EN'' "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'systemSuffix'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM "path/to/example.dtd"><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'systemSuffix'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM ''path/to/example.dtd''><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM "' || $exampledtd || '"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'systemSuffix'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC "-//EXAMPLE//not mapped//EN" "C:\another.dtd"><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example PUBLIC "-//EXAMPLE//not mapped//EN" "file:///C:/path/another.dtd"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'rewriteSystem'),

let $xml := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM "C:\another.dtd"><example/>'
let $exp := '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE example SYSTEM "file:///C:/path/another.dtd"><example/>'
let $result := resolver:resolveDOCTYPE($xml, $catfile)
let $result := resolver:resolveDOCTYPE($xml, $catalog)
return unit:assert-equals($result, $exp, 'rewriteSystem')

)
Expand All @@ -293,33 +293,33 @@ declare %unit:test function resolver:test_resolveDOCTYPE() {

declare %unit:test function resolver:test_resolveURI() {
let $base := file:base-dir()
let $catfile := file:resolve-path("test/catalog1.xml", $base)
let $catalog := file:resolve-path("test/catalog1.xml", $base)
let $exampledtd := file:path-to-uri(file:resolve-path("test/example.dtd", $base))
return (
let $uri := "https://example.org/example-v1.dtd"
let $result := resolver:resolveURI($uri, $catfile)
let $result := resolver:resolveURI($uri, $catalog)
return unit:assert-equals($result, $exampledtd, "uri"),

let $uri := "path/to/example.dtd"
let $result := resolver:resolveURI($uri, $catfile)
let $result := resolver:resolveURI($uri, $catalog)
return unit:assert-equals($result, $exampledtd, "uriSuffix"),

let $uri := "C:\file.txt"
let $result := resolver:resolveURI($uri, $catfile)
let $result := resolver:resolveURI($uri, $catalog)
return unit:assert-equals($result, "file:///C:/path/file.txt", "rewriteURI"),

let $uri := "http://not-mapped.org/"
let $result := resolver:resolveURI($uri, $catfile)
let $result := resolver:resolveURI($uri, $catalog)
return unit:assert-equals($result, $uri, "not mapped")
)
};


declare %unit:test function resolver:test_parse-xml() {
let $base := file:base-dir()
let $catfile := file:resolve-path("test/catalog1.xml", $base)
let $catalog := file:resolve-path("test/catalog1.xml", $base)
let $examplexml := file:resolve-path("test/example.xml", $base)
let $result := resolver:parse-xml($examplexml, $catfile)
let $result := resolver:parse-xml($examplexml, $catalog)
return unit:assert-equals($result, document{<example att="default">expansion from external DTD</example>})
};

Expand Down

0 comments on commit fd55700

Please sign in to comment.