Странное поведение в комментариях XQuery

У меня есть набор преобразований XQuery, которые я выполняю для файлов, хранящихся в базе данных Sedna. Все они имеют примерно следующий формат:

declare namespace ns0 = "http://www.someuri.com/foo.xsd";
declare namespace ns1 = "http://www.someuri.com/bar.xsd";

(:Declare a few functions like the following:)
declare function local:to-xs-boolean(
    $string as xs:string?
)
as xs:boolean? {
    if (fn:upper-case($string) = 'Y') then
        xs:boolean('true')
    else
        if (fn:upper-case($string) = 'N') then
            xs:boolean('false')
        (:if it isn't Y or N then attempt a normal cast - this will fail if it
        it isn't any of 'true', 'false', 1, or 0 :)
        else
            if ($string != '') then
                xs:boolean($string)
            else
                ()
        (:endif:)
    (:endif:)
};

(:Omitted several other functions:)

(:Start the main program:)

(: { :)
for $formName in /ns0:formName
return
        <ns1:newFormName>
            {
                let $address := $formName/ns0:Address
                return
                    <NewAddress>{
                        (:Omitted code and elements unrelated to this question:)
                    }</NewAddress>
            }
            (:Omitted code and elements unrelated to this question:)
        </ns1:newFormName>

А теперь вопрос. Вы видите эту строку прямо над «for», которая гласит: «(: {:) '? Это должен быть комментарий, но по какой-то причине он имеет решающее значение для правильной работы моего запроса. Если я удалю его полностью (или уберу '{' внутри комментария), я получу

SEDNA Message: ERROR XPDY0002
It is a dynamic error if evaluation of an expression relies on some part of the dynamic context that has not been assigned a value.

Если я раскомментирую это (так что в строке будет только "{"), я получу

SEDNA Message: ERROR XPST0003
It is a static error if an expression is not a valid instance of the grammar defined in A.1 EBNF.
Details: at (393:1), syntax error, unexpected {
         at (798:33), syntax error, unexpected end of file, expecting "," or }

Если он и раскомментирован, и добавлен соответствующий знак "}" в конец файла, я получаю

SEDNA Message: ERROR XPST0003
It is a static error if an expression is not a valid instance of the grammar defined in A.1 EBNF.
Details: at (393:1), syntax error, unexpected {

Если я добавлю к этому комментарию другой текст (например, '(: text foo bar baz () blah {:)'), он будет продолжать работать, пока я оставлю там этот '{'.

Кто-нибудь когда-нибудь видел это раньше или имел какое-либо представление о том, что может быть причиной этого? На самом деле это не критическая проблема (я могу просто убедиться, что у меня есть '(: {:)' во всех моих преобразованиях), но это действительно вызывает у меня любопытство. Так что спасибо за любую помощь или даже за то, что вы просто присоединились ко мне в недоумении.

О, еще одно небольшое замечание - я не знаю, имеет ли это какое-либо значение, но я запускаю запрос из Java с помощью API Sedna Чарльза Фостера (http://www.cfoster.net/sedna/)



Изменить: это другой запрос, который я только что написал, который показывает ту же проблему. Мне это кажется воспроизводимым, но если это связано с синтаксической ошибкой, возможно, я просто воспроизвожу синтаксическую ошибку. Я оставлю и старую, чтобы не запутать будущих зрителей этого вопроса.

declare namespace ns0 = "http://www.someuri.com/InitialSchema.xsd";
declare namespace ns1 = "http://www.someuri.com/FinalSchema.xsd";

declare function local:to-address(
    $recipient as xs:string?,
    $line1 as xs:string?,
    $line2 as xs:string?,
    $line3 as xs:string?,
    $city as xs:string?,
    $provinceOrState as xs:string?,
    $country as xs:string?,
    $postalOrZIP as xs:string?
)
as element() {
    if (fn:upper-case($country) = 'CA' or fn:upper-case($country) = 'US') then
        if (fn:upper-case($country) = 'CA') then
            <CanadianAddress>
                <City>{ $city }</City>
                <Country>{ $country }</Country>
                <PostalCode>{ $postalOrZIP }</PostalCode>
                <Province>{ $provinceOrState }</Province>
                <Recipient>{ fn:normalize-space($recipient) }</Recipient>
                <StreetAddress>{ $line1 }</StreetAddress>
                <StreetAddress>{ $line2 }</StreetAddress>
                <StreetAddress>{ $line3 }</StreetAddress>
                <StreetAddress/>
            </CanadianAddress>
        else
            <USAddress>
                <City>{ $city }</City>
                <Country>{ $country }</Country>
                <ZipCode>{ $postalOrZIP }</ZipCode>
                <State>{ $provinceOrState }</State>
                <Recipient>{ fn:normalize-space($recipient) }</Recipient>
                <StreetAddress>{ $line1 }</StreetAddress>
                <StreetAddress>{ $line2 }</StreetAddress>
                <StreetAddress>{ $line3 }</StreetAddress>
            </USAddress>        
        (:endif:)
    else
        if ($country != '') then        
            <InternationalAddress>
                <City>{ $city }</City>
                <Country>{ $country }</Country>
                <PostalCode>{ $postalOrZIP }</PostalCode>
                <Recipient>{ fn:normalize-space($recipient) }</Recipient>
                <StreetAddress>{ $line1 }</StreetAddress>
                <StreetAddress>{ $line2 }</StreetAddress>
                <StreetAddress>{ $line3 }</StreetAddress>
            </InternationalAddress>
        else
            <CanadianAddress>
                <City>{ $city }</City>
                <Country>{ $country }</Country>
                <PostalCode>{ $postalOrZIP }</PostalCode>
                <Province>{ $provinceOrState }</Province>
                <Recipient>{ fn:normalize-space($recipient) }</Recipient>
                <StreetAddress>{ $line1 }</StreetAddress>
                <StreetAddress>{ $line2 }</StreetAddress>
                <StreetAddress>{ $line3 }</StreetAddress>
                <StreetAddress/>
            </CanadianAddress>
        (:endif:)
    (:endif:)
};


(:{:)
for $addressForm1 in /ns0:AddressForm
let $token := xs:integer(data($addressForm1/ns0:submissionID))
return
        <ns1:NewAddressForm>
            <SubmissionID>{ data($addressForm1/ns0:submissionID) }</SubmissionID>
            {
                let $currentAddress := $addressForm1/ns0:currentAddress
                return
                    <NewAddress>{
                        local:to-address(
                            concat(
                                $addressForm1/ns0:fullName/ns0:firstName,
                                ' ',
                                substring(data($addressForm1/ns0:fullName/ns0:middleName), 1, 1),
                                ' ',
                                $addressForm1/ns0:fullName/ns0:lastName
                            ),
                            data($currentAddress/ns0:line1),
                            data($currentAddress/ns0:line2),
                            data($currentAddress/ns0:line3),
                            data($currentAddress/ns0:city),
                            data($currentAddress/ns0:provinceOrState),
                            data($currentAddress/ns0:country),
                            data($currentAddress/ns0:postalOrZipCode)
                        )
                    }</NewAddress>
            }
        </ns1:NewAddressForm>

А вот несколько примеров данных для нового запроса.

<?xml version="1.0"?>
<ns0:AddressForm xmlns:ns0="http://www.someuri.com/InitialSchema.xsd">
    <ns0:submissionID>23774</ns0:submissionID>
    <ns0:fullName>
        <ns0:firstName>First</ns0:firstName>
        <ns0:middleName>Middle</ns0:middleName>
        <ns0:lastName>Last</ns0:lastName>
    </ns0:fullName>
    <ns0:currentAddress>
        <ns0:line1>Line 1</ns0:line1>
        <ns0:line2>Line 2</ns0:line2>
        <ns0:line3>Line 3</ns0:line3>
        <ns0:city>City</ns0:city>
        <ns0:provinceOrState>Province</ns0:provinceOrState>
        <ns0:postalOrZipCode>H0H 0H0</ns0:postalOrZipCode>
        <ns0:country>CA</ns0:country>
    </ns0:currentAddress>
</ns0:AddressForm>

Если за этим стоит синтаксическая ошибка, не мог бы кто-нибудь указать мне, на какой строке она находится?


person Jason    schedule 17.02.2011    source источник
comment
Это очень правильный синтаксис XQuery. похоже, у вашего Java-слоя XQueryService xQuery Parser возникла проблема?   -  person kadalamittai    schedule 18.02.2011
comment
@kadalamittai Да, может быть, это то, что здесь происходит. Хотя я все еще нахожу это очень странным. Возможно, я мог бы понять, что у парсера проблемы, когда в комментарии есть несоответствующий знак '{', но проблемы, когда их нет, для меня странно.   -  person Jason    schedule 18.02.2011
comment
Похоже на ошибку и в Saxon 9.3.04EE. Интересно, что скажет @ Майкл-Кей ...   -  person Dimitre Novatchev    schedule 18.02.2011
comment
@Dimitre: Проверьте мой ответ. Я не могу воспроизвести это с правильным синтаксисом.   -  person    schedule 18.02.2011


Ответы (1)


Проблема в следующей строке:

for $formName in /ns0:formName

В Sedna (помните, что Sedna - это база данных, а не процессор XQuery) нет способа определить элемент контекста по умолчанию (см. XQuery 1.0, 2.1.2 Dynamic Context) перед выполнением запроса. Таким образом, он не знает, как оценивать ./ns0:formName (что эквивалентно простому /ns0:formName) - он просто не знает, что . означает в данном случае.

Вы должны загрузить документ, который хотите обработать, в базу данных, а затем получить к нему доступ с помощью функции doc():

for $formName in doc('forms')/ns0:formName

Насколько мне известно, вы также можете попробовать API XQJ Чарльза Фостерса для Sedna (который должен быть в любом случае лучше, чем XML: DB API), который поддерживает определение элемента контекста.

Кстати, если у вас есть вопросы по XML: DB или XQJ от Sedna, лучше задавать их прямо в списке обсуждений sedna. Есть очень хорошие шансы, что Чарльз вам ответит.

person Shcheklein    schedule 19.02.2011