Как использовать или реализовать массивы в XQuery?

Есть ли встроенная поддержка массива в XQuery? Например, если мы хотим реализовать простую java-программу в xquery, как бы мы это сделали:

(Я не прошу переводить всю программу в xquery, а просто спрашиваю, как реализовать массив в строке номер 2 приведенного ниже кода в xquery? Я также использую функции marklogic/xdmp).

java.lang.String test = new String("Hello XQuery");
char[] characters = test.toCharArray();

for(int i = 0; i<characters.length; i++) {
    if(character[i] == (char)13) { 
        character[i] = (char) 0x00;
    }
}

Legend:

hex 0x00 dec 0 : null
hex 0x0d dec 13: carriage return
hex 0x0a dec 10: line feed
hex 0x20 dec 22: dquote

person Ranjan Sarma    schedule 20.12.2012    source источник


Ответы (7)


Проблема с преобразованием вашего примера кода в XQuery заключается не в отсутствии поддержки массивов, а в том, что x00 не является допустимым символом в XML. Если бы не эта проблема, вы могли бы выразить свой запрос с помощью простого вызова функции:

translate($input, '&#x13;', '&#x00;')

Теперь вы можете возразить, что это обман, просто так получилось, что есть функция, которая делает именно то, что вы пытаетесь сделать вручную. Но если бы этой функции не существовало, вы могли бы запрограммировать ее в XQuery: для строк доступно достаточно примитивов, чтобы вы могли манипулировать ими как угодно. Если вам нужно (а это бывает редко), вы можете преобразовать строку в последовательность целых чисел с помощью функции string-to-codepoints(), а затем воспользоваться всеми возможностями XQuery для манипулирования последовательностями.

Урок заключается в том, что когда вы используете декларативный язык, такой как XQuery или XSLT, не пытайтесь использовать те же приемы низкоуровневого программирования, которые вам приходилось использовать в более примитивных языках. Обычно есть гораздо более прямой способ выразить проблему.

person Michael Kay    schedule 20.12.2012
comment
исходная проблема заключалась в том, чтобы извлечь текстовое содержимое из узлов в формате xml и вывести его в формат csv (значения, разделенные запятыми), который понятен ms-excel, путем экранирования некоторых специальных символов, таких как dquote(), запятая (,), new- строка(\n) или перевод строки(\r). Мне нужна помощь в том, как это сделать с помощью xquery. И будет ли это перегрузкой, если размер файла xml достигает ГБ? если да, то что было бы лучшим подходом к этой проблеме? Спасибо за вашу ценную помощь. - person Ranjan Sarma; 20.12.2012
comment
Лучше сначала задать вопрос, на который вы хотите получить ответ. Для многогигабайтного XML вы, вероятно, захотите использовать потоковый синтаксический анализатор или анализатор, ориентированный на события, чтобы использование памяти оставалось постоянным. - person mblakele; 20.12.2012
comment
Некоторые процессоры XQuery имеют некоторую поддержку потоковой передачи. Это слишком большой вопрос, чтобы задавать его в качестве дополнительного комментария. - person Michael Kay; 21.12.2012

XQuery имеет встроенную поддержку последовательностей. Функция tokenize() (как предложил @harish.ray) возвращает последовательность. Вы также можете построить его самостоятельно, используя фигурные скобки и запятые:

let $mysequence = (1, 2, 3, 4)

Последовательности — это упорядоченные списки, так что на это можно положиться. Это немного отличается от набора узлов, возвращаемого из XPath, они обычно упорядочены по документам.

С другой стороны: на самом деле все в XQuery является либо набором узлов, либо последовательностью. Даже если объявлена ​​функция, возвращающая одну строку или целое число, вы можете обрабатывать это возвращаемое значение, как если бы оно было последовательностью одного элемента. Нет необходимости в явном приведении типов, для которых в XQuery все равно нет конструкций. Такие функции, как fn:exists() и fn:empty(), работают всегда.

ХТХ!

person grtjn    schedule 20.12.2012

Просто ради интереса, вот как бы я сделал это в XQuery, если бы fn:translate не существовало. Я думаю, что предложение Майкла Кея в конечном итоге выглядело бы похоже.

let $test := "Hello XQuery"
return codepoints-to-string(
  for $c in string-to-codepoints($test)
  return if ($c eq 32) then 44 else $c)

Обратите внимание, что я изменил преобразование из-за проблемы, которую он указал: 0 не является допустимой кодовой точкой. Поэтому вместо этого я перевел пробелы в запятые.

С MarkLogic другой вариант — использовать http://docs.marklogic.com/json:array. и связанные с ним функции. Функция json:set-item-at позволила бы кодировать в неопределенно императивном стиле. Кодирование обоих вариантов может быть хорошим учебным упражнением.

person mblakele    schedule 20.12.2012

Есть два способа сделать это.

  • Во-первых, вы можете создать объект XmlResults, используя XmlManager.createResults(), и использовать XmlResults.add(), чтобы добавить к нему свои строки. Затем вы можете использовать объект XmlResults, чтобы установить значение переменной в XmlQueryContext, которое можно использовать в вашем запросе.

    Пример:

    XmlResults values = XMLManager.createResults();
    values.add(new XmlValue("value1"));
    values.add(new XmlValue("value2"));
    XmlQueryContext.setVariableValue("files", values);
    
  • Альтернативой является разделение строки в XQuery. Вы можете сделать это с помощью функции tokenize(), которая использует регулярное выражение для соответствия разделителю строк.

    http://www.w3.org/TR/xpath-functions/#func-tokenize

Спасибо.

person Harish Raj    schedule 20.12.2012

Небольшой прогноз: XQuery 3.1 обеспечит встроенную поддержку массивов. См. http://www.w3.org/TR/xquery-31/ для подробнее.

person Christian Grün    schedule 09.08.2014

Вы можете построить массив следующим образом:

$myArray = tokenize('a b c d e f g', '\s')
// $myArray[3] -> c 

Обратите внимание, что первый индекс этого псевдомассива равен 1, а не 0!

person Schinski    schedule 25.11.2014

Поскольку вопрос Как использовать или реализовать массивы в XQuery? считается общим (и, таким образом, отображается в результатах поиска по этой теме), я хотел бы добавить общий ответ для дальнейшего использования (сделав его вики сообщества, чтобы другие могли расширяться):

Как уже намекал Кристиан Грюн, в XQuery 3.1 XQuery получил собственный тип данных массива, который является подтипом типа данных функции.

Поскольку массив — это «упорядоченный список значений», как и последовательность XPath/XQuery, первый вопрос, который может возникнуть, таков: в чем разница? Ответ прост: последовательность не может содержать другую последовательность. Все последовательности автоматически выравниваются. Не так массив, который может быть массивом массивов. Точно так же, как последовательности, массивы в XQuery также могут иметь любое сочетание любых других типов данных.

Собственный тип данных массива XQuery может быть выражен одним из двух способов: как [] или через array {}. Разница в том, что при использовании прежнего конструктора запятая считается «жесткой» запятой, что означает, что следующий массив состоит из двух элементов:

[ ("apples", "oranges"), "plums" ]

в то время как следующее будет состоять из трех членов:

array { ("apples", "oranges"), "plums" }

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

Поскольку массив является подтипом функции, массив можно рассматривать как анонимную функцию, которая принимает единственный параметр — числовой индекс. Таким образом, чтобы получить третий член массива с именем $foo, мы можем написать:

$foo(3)

Если массив содержит другой массив в качестве члена, вы можете связать вызовы функций вместе, как в:

$foo(3)(5)

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

$foo?(3)

снова вернет третий член массива, а

$foo?(3, 6)

вернет членов 3 и 6.

Скобки можно опускать при работе с литеральными целыми числами. Однако круглые скобки необходимы для формирования индекса поиска из динамического выражения, например:

$foo?(3 to 6)

здесь выражение в скобках оценивается как последовательность целых чисел, и, таким образом, выражение будет возвращать последовательность элементов all от позиции индекса 3 до позиции индекса 6.

Звездочка * используется как оператор подстановки. Выражение

$foo?*

вернет последовательность всех элементов массива. Опять же, цепочка возможна:

$foo?3?5

соответствует предыдущему примеру $foo(3)(5).

Более подробную информацию можно найти в официальной спецификации: XML Path Language ( XPath) 3.1 / 3.11.2 Массивы

Также был реализован новый набор функций, специфичных для массивов. Эти функции находятся в пространстве имен http://www.w3.org/2005/xpath-functions/array, которое обычно имеет префикс array, и ссылки на них можно найти здесь: Функции и операторы XPath и XQuery 3.1 / 17.3 Функции, работающие с массивами

person Community    schedule 28.07.2020