Как объявить несколько пространств имен по умолчанию в XQuery

Добрый день!

Я продолжаю искать, возможно ли объявить несколько пространств имен по умолчанию в XQuery?

Образец XML, который я использую, имеет 2 пространства имен по умолчанию:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
....
  <wsMessageHeader xmlns="http://integration.sampleabc.com/common/header/WSMessageHeader/v2">
........
</wsMessageHeader> 

<queryContactGlobalPreferences xmlns="http://integration.sampleabc.com/interfaces/queryContactGlobalPreferences/v1/queryContactGlobalPreferences.xsd">
</queryContactGlobalPreferences >
...
</soapenv:Envelope>

Поэтому я объявил в запросе два пространства имен по умолчанию:

declare namespace soapenv='.......'; 
declare default element namespace '......'; 
declare default element namespace '........'; 

Вывод: когда я выполняю запрос, я всегда получаю эту ошибку. Если я удаляю одно пространство имен по умолчанию, оно работает на этом узле, но мне также нужно запросить другой узел. Кажется, он разрешает только 1 пространство имен по умолчанию. Есть ли обходной путь для этого?

Вот ошибка:

Error on line 1 column 264 
  XPST0003: XQuery syntax error in #...lare default element namespace#:
    Namespace declarations cannot follow variables, functions, or options

person Dominic Hong    schedule 20.11.2015    source источник


Ответы (2)


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

Как правило, вы объявляете пространство имен по умолчанию наиболее часто используемым в ваших запросах. Назначьте другим префикс (как вы уже сделали для soapenv) и используйте префикс для любых элементов в этом пространстве имен. Однако вы, вероятно, могли бы избавить себя от некоторой путаницы и просто присвоить всему префикс, чтобы не было двусмысленности при чтении вашего запроса.

for $e in $doc//soapenv:Envelope
let $header := $e/headerns:wsMessageHeader
let $prefs := $e/prefsns:queryContactGlobalPreferences
return element stuff {
  $header, $prefs
}

Ключевой концепцией здесь является то, что пространства имен — это все, что действительно имеет значение при выборе элементов. Вы можете назначать им префиксы или нет, и вам не нужно использовать те же префиксы, что и в ваших документах, если пространства имен, связанные с объявленными вами префиксами, совпадают с теми, которые связаны с элементами, которые вы намереваетесь выбрать из документа. .

person wst    schedule 20.11.2015
comment
Да!! я понял, что назначение пространства имен будет лучшим решением. Однако программа, которую я разрабатываю, является автоматизацией, и конечные пользователи ленивы назначать префикс для каждого файла xml. Есть ли способ автоматизировать автоматическое назначение префикса для пространства имен dafault? ТИА - person Dominic Hong; 20.11.2015
comment
Как вы упомянули в другом комментарии, можно использовать подстановочные знаки пространства имен. Таким образом, хотя это и не рекомендуется, вы можете просто использовать * вместо префикса, например (используя приведенный выше пример): $doc//*:Envelope, $e/*:wsMessageHeader, $e/*:queryContactGlobalPreferences, и это позволит избежать необходимости объявлять пространства имен и префиксы. - person wst; 20.11.2015

У вас может быть только одно пространство имен элементов по умолчанию. Пространство имен по умолчанию также используется для сгенерированных элементов, более одного пространства имен элементов по умолчанию может привести к неопределенному поведению. Какое пространство имен выбрать? У элемента может быть только одно пространство имен!

Объявление пространств имен

Вместо этого объявите пространства имен с префиксом (вы можете использовать произвольные, только URI пространства имен должен соответствовать документу):

declare namespace soapenv = "http://schemas.xmlsoap.org/soap/envelope/";
declare namespace messageHeader = "://integration.sampleabc.com/common/header/WSMessageHeader/v2";
declare namespace preferences = "http://integration.sampleabc.com/interfaces/queryContactGlobalPreferences/v1/queryContactGlobalPreferences.xsd";

и адресовать элемент, используя префиксы, например

//soapenv:Envelope/messageHeader:wsMessageHeader

Подстановочный знак пространства имен

В качестве альтернативы для специальных запросов, в которых определение пространств имен может выглядеть как ненужные накладные расходы и проблемы, вы также можете использовать оператор подстановочных знаков пространства имен *, соответствующий всем пространствам имен, для имитации нескольких пространств имен элементов по умолчанию. Тогда запрос выше будет

//*:Envelope/*:wsMessageHeader

Я настоятельно не рекомендую использовать это для более продолжительного производственного кода, поскольку объявление пространств имен может выявить проблемы, которые в противном случае просто пропускались бы без уведомления, и, в конце концов, упрощает чтение и понимание запросов, поскольку вы знаете источник или тип элементов, которые вы в настоящее время обрабатываете. .

person Jens Erat    schedule 20.11.2015
comment
Хм, работает ли подстановочный знак пространства имен? это работает в XQuery в javaBeans? - person Dominic Hong; 20.11.2015
comment
Я ничего не знаю о JavaBeans, но подстановочные знаки пространства имен определены, начиная с XQuery 1.0, и должны поддерживаться всеми процессорами XQuery, совместимыми со стандартами. - person Jens Erat; 20.11.2015