Как динамически ссылаться на узлы в xdmp: node-replace в MarkLogic?

В моей функции обновить-заменить я пытаюсь динамически заменить узел XML в одном из моих файлов источников данных XML в MarkLogic, вызывая xdmp:node-replace, как показано ниже:

declare function update-lib:update-rec($doc as xs:string, $path as xs:string, $country as xs:string, $name as xs:string, $population as xs:integer, $latitude as xs:decimal, $longitude as xs:decimal) as document-node() {
    (: read lock acquired :)
    fn:doc($doc),

    xdmp:node-replace(fn:doc($doc)/$path,
        <city>
            <country>{$country}</country>
            <name>{$name}</name>
            <population>{$population}</population>
            <latitude>{$latitude}</latitude>
            <longitude>{$longitude}</longitude>
        </city>
    ),


    (: after the following statement, txn ends and locks released :)
    xdmp:commit()
};

Функция принимает 7 аргументов, из которых 1-й аргумент - это путь к исходному XML-файлу, 2-й - это путь внутри XML-файла к обновляемому узлу, а остальные соответствуют значениям дочерних элементов.

Когда я вызываю xdmp:node-replace для обновления данных, я обнаруживаю следующую ошибку:

внутренняя ошибка сервера 500

XDMP-ARGTYPE: (err: XPTY0004) xdmp: node-replace ("/ cities / city [3961]", JPMiyoshi56958) - arg1 не относится к типу node () ...

Поэтому я решил оценить arg1, чтобы гарантировать, что node () будет передан как 1-й аргумент node-replace:

xdmp:node-replace(xdmp:eval(fn:doc($doc)/$path),
    <city>
        <country>{$country}</country>
        <name>{$name}</name>
        <population>{$population}</population>
        <latitude>{$latitude}</latitude>
        <longitude>{$longitude}</longitude>
    </city>
),

Теперь вместо этого я получаю следующую ошибку:

XDMP-UPEXTNODES: xdmp: node-replace (fn: doc ("/ content / Users / Tako / Sites / MarkLogic / xml / worldcities / import / cities1000_02.xml") / cities / city [3961], JPMiyoshi56958) - Невозможно обновить внешние узлы ...

Немного погуглив, я нашел это. Похоже на проблему с xdmp:eval и его контекстом:

http://developer.marklogic.com/pipermail/general/2008-September/001753.html

Я попробовал предлагаемый здесь обходной путь, используя fn:concat, чтобы все было построено в виде строки, включая xdmp:node-replace, и оценив весь оператор.

xdmp:eval(fn:concat('xdmp:node-replace(fn:doc("', $doc, '")', $path,
    ', ', '<city><country>',$country,'</country><name>',$name,'</name><population>',$population,'</population><latitude>',$latitude,'</latitude><longitude>',$longitude,'</longitude></city>', ')')),

Когда я пробовал это, приложение очень долго сидит и ждет, прежде чем истечет время ожидания. внутренняя ошибка сервера 500

SVC-EXTIME: xdmp: node-replace (fn: doc ("/ content / Users / Tako / Sites / MarkLogic / xml / worldcities / import / cities1000_17.xml") / cities / city [3961], JPMiyoshi56958) - Время лимит превышен ...

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

Может кто-нибудь пролить свет на это?


person takoloco    schedule 02.07.2013    source источник
comment
Но если вы попробовали xdmp: unpath () со своим первым скриптом, второй аргумент аргумента - $ path, чтобы оценить строку как XPath и вернуть соответствующий узел (ы). Дополнительную информацию можно найти на странице docs.marklogic.com/xdmp:unpath.   -  person Navin Rawat    schedule 02.07.2013
comment
Это действительно сработало. Спасибо!   -  person takoloco    schedule 02.07.2013


Ответы (1)


В первом решении вы применяете строковое значение к каждому узлу документа, возвращаемому fn:doc($doc). Таким образом вы получите только строковое значение самого $ xpath. Второе решение также эффективно принимает значение $ xpath и пытается его оценить. Это может привести к появлению большого количества узлов, которые потенциально все обновляются.

Я не совсем понимаю, почему вы получаете XDMP-UPEXTNODES и тайм-ауты, но подойдет следующее:

Заменять:

fn:doc($doc)/$path

с участием:

xdmp:value(fn:concat("fn:doc($doc)", $path))

HTH!

person grtjn    schedule 02.07.2013
comment
Работал как шарм! Спасибо! - person takoloco; 02.07.2013