2017-02-07 4 views
0

Я использую Saxon HE 9.7.0 для преобразования некоторого XSLT 2.0. В моем файле я пытаюсь выбрать поддерево и поместить его в переменную, чтобы использовать его позже.Доступ к поддереву, который хранится в переменной, вызывает исключение

Входная XML:

<?xml version="1.0"?> 
<documents> 
    <document> 
     <code>009190</code> 
     <index>3</index> 
    </document> 
    <document> 
     <code>583876</code> 
     <index>1</index> 
    </document> 
    <document> 
     <code>277410</code> 
     <index>2</index> 
    </document> 
</documents> 

Теперь в моей XSLT Я выбираю документ с самым низким индексом и хочу использовать свой код позже (переменная documents содержит корень дерево):

<xsl:variable name="selectedDocument"> 
    <xsl:variable name="lowestDocumentIndex" select="min($documents/document/orderIndex)" /> 
    <xsl:value-of select="$documents/documents[index=$lowestDocumentIndex]" /> 
</xsl:variable> 

<!-- Now later on, I want to use the contents of the selected document: --> 
<xsl:value-of select="$selectedDocument/code" /> 

Это вызывает исключение в синтаксическом анализаторе, который выглядит следующим образом:

Caused by: java.lang.RuntimeException: Internal error evaluating template rule at line 23 in module 
    at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:366) 
    at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:456) 
    at net.sf.saxon.Controller.transformDocument(Controller.java:2291) 
    at net.sf.saxon.Controller.transform(Controller.java:1863) 
    at net.sf.saxon.s9api.XsltTransformer.transform(XsltTransformer.java:579) 
    at net.sf.saxon.jaxp.TransformerImpl.transform(TransformerImpl.java:185) 
    at de.haba.genex.exp.core.model.nodes.XSLTTransformationNode.lambda$process$0(XSLTTransformationNode.java:146) 
    ... 40 more 
Caused by: java.lang.ClassCastException: net.sf.saxon.value.UntypedAtomicValue cannot be cast to net.sf.saxon.om.NodeInfo 
    at net.sf.saxon.expr.SimpleStepExpression.iterate(SimpleStepExpression.java:108) 
    at net.sf.saxon.expr.Atomizer.iterate(Atomizer.java:293) 
    at net.sf.saxon.expr.AtomicSequenceConverter.iterate(AtomicSequenceConverter.java:249) 
    at net.sf.saxon.expr.SystemFunctionCall.evaluateArguments(SystemFunctionCall.java:360) 
    at net.sf.saxon.expr.FunctionCall.iterate(FunctionCall.java:544) 
    at net.sf.saxon.expr.Expression.evaluateItem(Expression.java:763) 
    at net.sf.saxon.expr.Expression.evaluateAsString(Expression.java:859) 
    at net.sf.saxon.expr.instruct.SimpleNodeConstructor.processLeavingTail(SimpleNodeConstructor.java:186) 
    at net.sf.saxon.expr.instruct.ValueOf.processLeavingTail(ValueOf.java:283) 
    at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:653) 
    at net.sf.saxon.expr.LetExpression.processLeavingTail(LetExpression.java:711) 
    at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:653) 
    at net.sf.saxon.expr.LetExpression.processLeavingTail(LetExpression.java:711) 
    at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:653) 
    at net.sf.saxon.expr.LetExpression.processLeavingTail(LetExpression.java:711) 
    at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:653) 
    at net.sf.saxon.expr.instruct.NamedTemplate.expand(NamedTemplate.java:257) 
    at net.sf.saxon.expr.instruct.CallTemplate.process(CallTemplate.java:356) 
    at net.sf.saxon.expr.LetExpression.process(LetExpression.java:568) 
    at net.sf.saxon.expr.instruct.ForEach.processLeavingTail(ForEach.java:453) 
    at net.sf.saxon.expr.LetExpression.processLeavingTail(LetExpression.java:711) 
    at net.sf.saxon.expr.instruct.Choose.processLeavingTail(Choose.java:835) 
    at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:149) 
    at net.sf.saxon.expr.LetExpression.process(LetExpression.java:568) 
    at net.sf.saxon.expr.instruct.ForEach.processLeavingTail(ForEach.java:453) 
    at net.sf.saxon.expr.LetExpression.processLeavingTail(LetExpression.java:711) 
    at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:653) 
    at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:353) 
    ... 46 more 

С XSLT 2.0 больше не хранить RTF, но сохраняя реальные временные деревья, разве это не должно работать?

Это всего лишь сокращенный пример того, что я пытаюсь сделать, у меня на самом деле есть <xsl:choose> в моем <xsl:variable>, а структура документа сложнее, но идея должна быть одинаковой.


EDIT: кажется, что моя проблема связана, что я передаю список документов в другой шаблон первым. Использование xsl:copy-of как написано в ответах, кажется, работает, но не тогда, когда я делаю следующее:

(Попробуйте его на http://xsltransform.net/ejivdHL/2)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:template match="/"> 
     <xsl:call-template name="processDocuments"> 
      <xsl:with-param name="docs" select="documents" /> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="processDocuments"> 
     <xsl:param name="docs" /> 

     <xsl:variable name="selectedDocument"> 
      <xsl:variable name="lowestDocumentIndex" select="min(doc/document/index)" /> 
      <xsl:copy-of select="doc/document[index=$lowestDocumentIndex]" /> 
     </xsl:variable> 

     <xsl:value-of select="$selectedDocument/document/code" /> 
    </xsl:template> 

</xsl:transform> 

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

ответ

0

Чтобы сохранить копию узлов, вам необходимо <xsl:copy-of select="$documents/documents[index=$lowestDocumentIndex]" /> вместо <xsl:value-of select="$documents/documents[index=$lowestDocumentIndex]" />. value-of создает текстовый узел со строковым значением (-ами) выбранного узла (ов).

Кроме того, некоторые ссылки/пути, похоже, не совпадают, при закреплении, что я получаю

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:template match="/"> 
     <xsl:variable name="selectedDocument"> 
      <xsl:variable name="lowestDocumentIndex" select="min(documents/document/index)" /> 
      <xsl:copy-of select="documents/document[index=$lowestDocumentIndex]" /> 
     </xsl:variable> 

     <!-- Now later on, I want to use the contents of the selected document: --> 
     <xsl:value-of select="$selectedDocument/document/code" /> 
    </xsl:template> 

</xsl:transform> 

вывода 583876 на http://xsltransform.net/ejivdHL.

Там действительно нет необходимости создавать временное дерево, вы можете просто выбрать оригинальный элемент ввода:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:template match="/"> 
     <xsl:variable name="lowestDocumentIndex" select="min(documents/document/index)" /> 
     <xsl:variable name="selectedDocument" select="documents/document[index=$lowestDocumentIndex]" /> 


     <!-- Now later on, I want to use the contents of the selected document: --> 
     <xsl:value-of select="$selectedDocument/code" /> 
    </xsl:template> 

</xsl:transform> 

Online на http://xsltransform.net/ejivdHL/1.

+0

Спасибо за ваш ответ - ваш первый пример работает, но кажется, что моя проблема лежит глубже. Я добавил более подробно на вопрос, возможно, у вас есть идея? – maxdev

+0

См. Исправления в http://xsltransform.net/ejivdHL/3, если у вас есть параметр 'docs', вам нужно ссылаться на него как' $ docs', а не как 'doc' (а также' docs'). –

+0

О, так, как это работает в этом примере. У меня все еще другая проблема в XSLT, но мне придется искать еще кое-что. – maxdev

0

Использование:

<xsl:variable name="lowestDocumentIndex" select="min($documents/document/index)" /> 
<xsl:variable name="selectedDocument" select="$documents/document[index=$lowestDocumentIndex]" /> 

кажется, что <xsl:value-of> в коде извлекается значение выбранного узла (сцепленных текстовых узлов) не сам узел.

К сожалению, ваш код не содержит $documents/documents. Обратите внимание, что последний s должен быть удален.

+0

Это не сработает, когда мне нужно использовать '' внутри, как я писал в своем последнем предложении – maxdev

0

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

Просто чтобы дать немного предварительного анализа, ключ отказ

java.lang.ClassCastException: net.sf.saxon.value.UntypedAtomicValue cannot be cast to net.sf.saxon.om.NodeInfo 
at net.sf.saxon.expr.SimpleStepExpression.iterate(SimpleStepExpression.java:108) 

Это говорит нам, что это ошибка времени выполнения, и мы оцениваем «простое выражение шаг», который является чем-то например $ lhs/child :: X, где LHS является выражением, возвращающим одноэлемент, а RHS является выражением оси. Я могу сказать по номеру строки, что вы не выполняете последнюю версию обслуживания (поскольку приведение в NodeInfo теперь включено в строке 110). ClassCastException происходит потому, что LHS выражения будет узлом, но на самом деле является атомным значением, что означает, что что-то пошло не так в проверке типов, которая должна была поймать это раньше. Это может быть ошибка в коде, которую мы не можем правильно подобрать и диагностировать.

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

Это предполагает два действия: (a) попробуйте использовать последний релиз службы саксонской версии (в настоящее время 9.7.0.14, но смотрите это место) и (b) если он снова сработает, отправьте полный текст на saxonica.plan .io. Благодаря!