Rico Strydom
Rico Strydom

Reputation: 571

XQuery : xml declaration is dropped when if statement is used

Consider the following three statements.

1:

XMLSERIALIZE(DOCUMENT XMLQUERY(q'^
                                copy $i := $doc modify (
                                    for $j in $i/tdfmt/text()[1]
                                return 
                                    insert node ( $text, $br, '
' ) before $j
                                )
                                return $i
                               ^'
        PASSING
            XMLTYPE(OIT.INFTXT)  AS "doc",
            LENGTH(EXTRACTVALUE(XMLTYPE(OIT.INFTXT),'tdfmt/text()[1]')) AS "len",
            'NEW TEXT TO INSERT' AS "text",
            XMLTYPE('<br/>')            AS "br"
        RETURNING CONTENT)  AS CLOB INDENT SIZE=4 )
        AS NEW_INFTXT_A

2:

XMLSERIALIZE(DOCUMENT XMLQUERY(q'^
                                copy $i := $doc modify (
                                    for $j in $i/*
                                return 
                                    insert node ( $text, $br, '&#xa;' ) into $j
                                )
                                return $i
                               ^'
        PASSING
            XMLTYPE(OIT.INFTXT)  AS "doc",
            LENGTH(EXTRACTVALUE(XMLTYPE(OIT.INFTXT),'tdfmt/text()[1]')) AS "len",
            'NEW TEXT TO INSERT' AS "text",
            XMLTYPE('<br/>')            AS "br"
        RETURNING CONTENT)  AS CLOB INDENT SIZE=4 )
        AS NEW_INFTXT_B

3:

XMLSERIALIZE(DOCUMENT XMLQUERY(q'^                                      
                                if ($len>0) 
                                then    
                                    copy $i := $doc modify (
                                        for $j in $i/tdfmt/text()[1]
                                    return 
                                        insert node ( $text, $br, '&#xa;' ) before $j
                                    )
                                    return $i
                                else    
                                    copy $i := $doc modify (
                                        for $j in $i/*
                                    return 
                                        insert node ( $text, $br, '&#xa;' ) into $j
                                    )
                                    return $i
                               ^'
        PASSING
            XMLTYPE(OIT.INFTXT)  AS "doc",
            LENGTH(EXTRACTVALUE(XMLTYPE(OIT.INFTXT),'tdfmt/text()[1]')) AS "len",
            'NEW TEXT TO INSERT' AS "text",
            XMLTYPE('<br/>')            AS "br"
        RETURNING CONTENT)  AS CLOB INDENT SIZE=4 )
        AS NEW_INFTXT1

The idea is to switch between 1 and 2 depending on the length of my node. In the output of 3, I noticed that the xml declaration <?xml version="1.0"?> is omitted while with 1 and 2 it is present. Any idea why adding an if then else statement would cause this behaviour and what I should to to prevent the declaration form being dropped.

Upvotes: -1

Views: 53

Answers (1)

Alex Poole
Alex Poole

Reputation: 191560

Not sure why it has that effect, but you can avoid it by putting the if within the modify:

XMLSERIALIZE(DOCUMENT XMLQUERY(q'^                                      
                                copy $i := $doc modify (
                                    if ($len>0) 
                                    then    
                                        for $j in $i/tdfmt/text()[1]
                                        return 
                                        insert node ( $text, $br, '&#xa;' ) before $j
                                    else    
                                        for $j in $i/*
                                        return 
                                        insert node ( $text, $br, '&#xa;' ) into $j
                                )
                                return $i
                               ^'
        PASSING
            XMLTYPE(OIT.INFTXT)  AS "doc",
            LENGTH(EXTRACTVALUE(XMLTYPE(OIT.INFTXT),'tdfmt/text()[1]')) AS "len",
            'NEW TEXT TO INSERT' AS "text",
            XMLTYPE('<br/>')            AS "br"
        RETURNING CONTENT)  AS CLOB INDENT SIZE=4 )
        AS NEW_INFTXT1

You can also test for the existence of the node in the FLWOR, rather than passing $len in:

XMLSERIALIZE(DOCUMENT XMLQUERY(q'^                                      
            copy $i := $doc modify (
                if (exists($i/tdfmt/text()[1])) 
                then    
                    for $j in $i/tdfmt/text()[1]
                        return insert node ( $text, $br, $newline ) before $j
                else    
                    for $j in $i/*
                        return insert node ( $text, $br, $newline ) into $j
            )
            return $i
            ^'
        PASSING
            XMLTYPE(OIT.INFTXT)  AS "doc",
            'NEW TEXT TO INSERT' AS "text",
            XMLTYPE('<br/>') AS "br",
            CHR(10) AS "newline"
        RETURNING CONTENT)  AS CLOB INDENT SIZE=4 )
        AS NEW_INFTXT1

(also changed to pass $newline in as shown in a previous answer, just because I think it looks neater *8-)

fiddle

Upvotes: 0

Related Questions