2017-02-07 8 views
0

저는 Saxon HE 9.7.0을 사용하여 일부 XSLT 2.0을 변환하고 있습니다. 내 파일에서 하위 트리를 선택하고 나중에 사용하기 위해 변수에 넣으려고합니다.변수에 저장된 하위 트리에 액세스하면 예외가 발생합니다.

입력 XML :

<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" /> 

:

<?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 루트 트리를 포함) 이로 인해 파서에서 다음과 같은 예외가 발생합니다.

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> 내에 있고 문서 구조가 더 복잡하지만 생각은 동일해야합니다.


편집 : 내 문제는 내가 먼저 다른 템플릿으로 문서 목록을 통과 그와 관련된 것으로 보인다. 답변에 기록 된대로 xsl:copy-of 사용이 작동하는 것 같다,하지만 난 할 때 다음하지 :

잘못 무슨 일이 일어나고 있는지의

<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> 

더 이상의 아이디어 (http://xsltransform.net/ejivdHL/2에 그것을 밖으로 시도)? 여러 노드에 템플릿을 여러 번 사용하기 때문에 두 번째 템플릿을 사용해야합니다.

답변

0

노드 복사본을 저장하려면 <xsl:value-of select="$documents/documents[index=$lowestDocumentIndex]" /> 대신 <xsl:copy-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> 

http://xsltransform.net/ejivdHL에서 583876 출력을 얻을 고정 할 때, 일치되어 있지 않은 것 같습니다. http://xsltransform.net/ejivdHL/1에서

<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> 

온라인 : 임시 트리를 만들 필요가 정말 없다

, 당신은 단순히 원래의 입력 요소를 선택할 수 있습니다.

+0

답장을 보내 주셔서 감사합니다 - 첫 번째 예제가 작동하지만 내 문제가 더 깊어 보인다. 질문에 더 자세히 설명해 주셨습니다. 아이디어가 있습니까? – maxdev

+0

http://xsltransform.net/ejivdHL/3의 수정 사항을 보시오. 매개 변수'docs'를'docs'가 아닌'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

"색슨 내부 오류"를 말하는 stacktrace는 색슨 버그입니다. 우리가 이미 알고 있고 수정되었을 수도 있지만, 버그는 모두 같습니다. Saxon 버그를 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에서 전체 repro을 제출하십시오 .io. 감사!