Производительность функции суммирования XSLT / Xpath

Я часто использую этот xpath sum(preceding::*/string-length())

Он делает то, что мне нужно (обеспечивает подсчет символов всего текста до этого контекста в файле XML).

Проблема: это медленно.

Есть ли другая встроенная функция, которую я должен использовать вместо этого? Или расширение?

ОБНОВЛЕНИЕ:

Основываясь на комментарии Майкла Кея, я изучил XSLT 3.0 <accumulator>. Это была моя первая попытка с 3.0 (мне пришлось обновить OxygenXML, чтобы он заработал). Я не полностью адаптировал его к своим потребностям, но первоначальный тест, приведенный ниже, показывает многообещающие.

<xsl:output method="xml" />

<xsl:accumulator 
    name="f:string-summ"
    post-descent="f:accum-string-length"
    as="xs:integer"
    initial-value="0">
    <xsl:accumulator-rule 
        match="text/*" 
        new-value="$value + string-length()"/>
</xsl:accumulator>

<xsl:template match="text/*">
        <xsl:value-of select="f:accum-string-length()" />
</xsl:template>

Не по теме: Stack Overflow нужен тег «XSLT-3.0».


person Paulb    schedule 21.12.2013    source источник
comment
Какой анализатор / компилятор Xslt вы используете?   -  person rene    schedule 21.12.2013
comment
Для этого ... Я использую Saxon HE из командной строки.   -  person Paulb    schedule 21.12.2013
comment
Можете ли вы указать размер вашего xml, текущее время и целевое время?   -  person rene    schedule 21.12.2013
comment
Я запускаю преобразование идентичности, которое устанавливает атрибуты в определенные места в файле (в зависимости от размера текста). Шаблон больше ничего не делает. Создание xml-файла размером 5 МБ занимает 3 минуты 30 секунд. У меня действительно нет «цели» ... мне просто кажется, что 3 минуты означают, что я должен переоценить то, что я делаю.   -  person Paulb    schedule 21.12.2013


Ответы (2)


Если вы вызовете эту функцию для каждого узла, то производительность вашей таблицы стилей будет O (n ^ 2) по количеству узлов.

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

Попробуйте определить функцию памятки примерно так:

<xsl:function name="f:preceding-string-length" saxon:memo-function="yes">
  <xsl:param name="n" as="element()"/>
  <xsl:sequence select="sum(ancestor::*/preceding-sibling::*[1]/(f:preceding-string-length(.) + string-length(.)))"/>
</xsl:function>

Или используйте аккумулятор XSLT 3.0, что почти то же самое.

person Michael Kay    schedule 21.12.2013
comment
Аккумулятор XSLT 3.0 выглядит изящным решением. Я нашел спецификацию W3 и попробовал. OxygenXML с SaxonPE 9.5.0.2, появилось сообщение об ошибке Неизвестный аккумулятор системной функции. То, что я прочитал, указывало на то, что у Saxon должен быть аккумулятор ... он жив? - person Paulb; 22.12.2013
comment
Saxon 9.5 реализует аккумуляторы, как описано в проекте XSLT 3.0 от июля 2012 года. Дизайн немного изменился в проекте декабря 2013 года. - person Michael Kay; 22.12.2013

Я не думаю, что функция sum работает медленно, переход ко всем предыдущим элементам и вычисление длины строки всего содержимого требует больших затрат. Что касается его оптимизации, какой процессор XSLT 2.0 вы используете?

person Martin Honnen    schedule 21.12.2013
comment
Saxon позволяет профилировать таблицу стилей, см. saxonica.com/documentation/html/using -xsl /. Я не уверен, помогает ли это вашему коду. В своем комментарии к Рене вы также указываете, что ваша полная таблица стилей короткая, поэтому подумайте о том, чтобы показать ее в своем вопросе вместе с образцом ввода, показывающим структуру, которую вам нужно обработать, тогда, возможно, кто-то другой может предложить, как оптимизировать XSLT для Saxon или вообще. - person Martin Honnen; 21.12.2013
comment
Спасибо за идею, Мартин. Пытался ... и он сказал мне очевидное (он сказал с бесценной мудростью заднего взгляда), что сказал Майкл Кей ... см. Его ответ. Теперь я понимаю, что с размером некоторых моих документов, от 1 МБ до максимум 70 МБ, мне нужен подход, который выигрывал бы от потоковой обработки. - person Paulb; 22.12.2013