Есть ли какие-нибудь ограничения в Saxon-EE XSLT v3 Streaming? - PullRequest
0 голосов
/ 10 сентября 2018

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

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="ano contextutil"  xmlns:ano="java:StreamingGenericProcessor"
  xmlns:contextutil="java:GenericAnonymizerContextUtil">
 <xsl:mode streamable="yes"/>
 <xsl:output method="xml"/>
 <xsl:param name="context" as="class:java.lang.Object" xmlns:class="http://saxon.sf.net/java-type"/>
 <xsl:template match="internal/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="email/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="address/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="birthday/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="country/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="external/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="name/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="phone/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="city/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="id/text()"><xsl:value-of select="ano:uuid($context, current(), 'ID')"/></xsl:template>
 <xsl:template match="." >
   <xsl:copy validation="preserve">
     <xsl:apply-templates select="@*" />
     <xsl:apply-templates select="node()" />
   </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>

Но с этим он делает :

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="ano contextutil"  xmlns:ano="java:StreamingGenericProcessor"
  xmlns:contextutil="java:GenericAnonymizerContextUtil">
 <xsl:mode streamable="yes"/>
 <xsl:output method="xml"/>
 <xsl:param name="context" as="class:java.lang.Object" xmlns:class="http://saxon.sf.net/java-type"/>
 <xsl:template match="email/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="address/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="birthday/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="country/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="external/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="name/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="phone/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="city/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="id/text()"><xsl:value-of select="ano:uuid($context, current(), 'ID')"/></xsl:template>
 <xsl:template match="." >
   <xsl:copy validation="preserve">
     <xsl:apply-templates select="@*" />
     <xsl:apply-templates select="node()" />
   </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>

Я протестировал множество различных сценариев и Я пришел к выводу, что если у меня больше 9 «xsl: template», это не сработает!

РЕДАКТИРОВАТЬ: это не работает означает: на конкретный тег с именем "id" я применяю функцию Java. Если у меня более 9 «xsl: template», вывод не изменяется, и моя java-функция вообще не вызывается. У меня нет сообщения об ошибке

EDIT2: Если я заменю вызов функции Java, например, на "concat (current (), '_ID')", у меня будет такое же поведение, так что это не относится к функции Java все.

РЕДАКТИРОВАТЬ3:

Вот пример входных данных:

<?xml version="1.0" encoding="UTF-8"?>
<table>
  <row>
    <id>10</id>
    <email>fake@fake.com</email>
    <address>dsffe</address>
    <birthday>10/2018</birthday>
    <country>FR</country>
    <external>zz</external>
    <internal>ww</internal>
    <name>Jean</name>
    <phone>000000</phone>
    <city>Dfegd</city>
  </row>
  <row>
    <id>9</id>
    <email>fake@fake2.com</email>
    <address>sdfzefzef</address>
    <birthday>11/2012</birthday>
    <country>GB</country>
    <external>xx</external>
    <internal>yy</internal>
    <name>Jean-Claude</name>
    <phone>000000</phone>
    <city>dd</city>
  </row>

Это xsl, который всегда работает:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:mode streamable="yes"/>
 <xsl:output method="xml"/>
 <xsl:template match="email/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="address/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="birthday/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="country/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="external/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="name/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="phone/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="city/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="id/text()"><xsl:value-of select="concat(current(), '_ID')"/></xsl:template>
 <xsl:template match="." >
   <xsl:copy validation="preserve">
     <xsl:apply-templates select="@*" />
     <xsl:apply-templates select="node()" />
   </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>

Проблемный (тот же xsl с еще одним шаблоном):

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:mode streamable="yes"/>
 <xsl:output method="xml"/>
 <xsl:template match="email/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="address/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="birthday/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="country/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="external/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="internal/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="name/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="phone/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="city/text()"><xsl:value-of select="current()"/></xsl:template>
 <xsl:template match="id/text()"><xsl:value-of select="concat(current(), '_ID')"/></xsl:template>
 <xsl:template match="." >
   <xsl:copy validation="preserve">
     <xsl:apply-templates select="@*" />
     <xsl:apply-templates select="node()" />
   </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>

Я запускаю со следующей командной строкой:

java -cp Saxon-EE-9.8.0-14.jar  net.sf.saxon.Transform -s:test.xml -xsl:concat_not_working.xsl

Рабочий XSL правильно добавляет _ID к значению выходного тега id, тогда как не работает xsl не выполняет никаких преобразований.

Другая информация, если я запускаю без лицензии (то есть без потоковой передачи), обе таблицы стилей работают!

Я использую Saxon-EE 9.8.0-14 с пробной лицензией: может ли это быть недокументированным ограничением пробной лицензии?

1 Ответ

0 голосов
/ 10 сентября 2018

Ваша теория о том, что сбой происходит с 10 или более правилами, оказывается верной. Когда существует более 10 правил, соответствующих одной и той же комбинации вида узла / имени узла (в данном случае, всех текстовых узлов), Saxon-EE пытается избежать линейного поиска всех правил путем поиска критериев, которые являются подмножествами правил делиться общим. В этом случае он проверяет, может ли он сгруппировать правила в соответствии с предварительным условием на основе родительского элемента текстового узла.

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

Причина, по которой оптимизация работает неправильно, заключается в том, что на пути потоковой передачи для xsl: apply-templates данные контекста для оценки предусловий правила не инициализируются должным образом, что приводит к тому, что средство сопоставления правил считает, что предусловия не не удовлетворены.

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

Запуск нелицензированного обходит ошибку по двум причинам: он отключает оптимизацию цепочек правил и отключает потоковую передачу.

В качестве обходного пути просто удалите /text() из каждого правила вашего шаблона.

Зарегистрирован как ошибка здесь: https://saxonica.plan.io/issues/3901

Если вы не укажете иное, я отправлю новый тестовый набор на основе ваших тестовых данных и таблицы стилей в набор тестов W3C для XSLT 3.0.

...