Skip to content

[BUG] util:get-fragment-between returns unparsable XML when attribute contains square brackets #3685

Description

@joewiz

Describe the bug

When calling util:get-fragment-between() on a tree that contains an attribute with square brackets, the function returns a string that cannot be parsed.

Expected behavior

I expected the function to return parseable XML, as the source is valid XML.

For example, given a document, test.xml:

<root foo="[bar]">
    <x/>
    <y/>
</root>

... then the following query:

let $doc := doc("/db/test.xml")/root
let $beginning-node := $doc/x
let $ending-node := $doc/y
let $make-fragment := true()
let $display-root-namespace := true()
return
    util:get-fragment-between($beginning-node, $ending-node, $make-fragment, $display-root-namespace)

... will return a string that cannot be parsed as XML:

<root foo=" bar">
<x></x>
    </root"]>

Notice that:

  1. The attribute doesn't match the original (" bar" instead of "[bar]")
  2. The close tag is mangled (</root"]> instead of </root>)

To Reproduce

The following test extends tests already in https://github.com/eXist-db/exist/blob/develop/exist-core/src/test/xquery/util/get-fragment-between.xqm (added in #3328).

xquery version "3.1";

module namespace gfb = "http://exist-db.org/test/util/get-fragment-between";

declare namespace test = "http://exist-db.org/xquery/xqsuite";

declare variable $gfb:DOC3 :=
    <root foo="[bar]" xmlns="http://exist-db.org/xquery/xqsuite">
        <x/>
        <y/>
        <z/>
    </root>;

declare
    %test:setUp
function gfb:setup() {
    xmldb:create-collection("/db", "test-gfb"),
    xmldb:store("/db/test-gfb", "doc3.xml", $gfb:DOC3)
};

declare
    %test:tearDown
function gfb:teardown() {
    xmldb:remove("/db/test-gfb")
};

declare
    %test:assertTrue
function gfb:wrapped-fragment-with-bracked-in-attribute-is-parseable() {
    let $doc := doc("/db/test-gfb/doc3.xml")
    let $elems := $doc/test:root/*
    let $fragment := util:get-fragment-between($elems[1], $elems[2], true(), false())
    let $parsed := try { parse-xml($fragment) } catch * { $err:code }
    return
        $parsed instance of document-node(element(root))
};

The test suite returns:

<testcase name="wrapped-fragment-with-bracked-in-attribute-is-parseable"
    class="gfb:wrapped-fragment-with-bracked-in-attribute-is-parseable">
    <failure message="assertTrue failed." type="failure-error-code-1"/>
    <output>false</output>
</testcase>

... meaning that the result of util:get-fragment-between() can't be parsed.

Context (please always complete the following information):

  • OS: macOS 11.1
  • eXist-db version: eXist 4.7.1 and 5.3.0-SNAPSHOT 29a5330 20201227092937
  • Java Version: 1.8.0_275

Additional context

  • How is eXist-db installed? built from source
  • Any custom changes in e.g. conf.xml? none

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugissue confirmed as bug

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions