Jython: проблемы с выполнением XSLT

Игнорируя идентификацию, ниже код Jython при выполнении из командной строки создает вывод с самозакрывающимися тегами (без данных), как показано на рисунке ниже.

from java.io import *
import javax.xml
from java.io import StringReader, StringWriter
from javax.xml.transform import Transformer, TransformerFactory
from javax.xml.transform.stream import StreamResult, StreamSource

def obtainservicexslts():

print "In obtainservicexslts"    
print
source_xform_xml = """<?xml version='1.0' encoding='UTF-8'?>
<service-config>
  <service path="/Market">
    <request>         
      <rule transform="local:///services/xslt/MarketRequest.xslt">Transform</rule>
    </request>
    <response>
      <rule transform="local:///services/xslt/MarketResponse.xslt">Transform</rule>          
    </response>        
  </service>
</service-config>"""

source_xform_xslt = """<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="xsltkey" match="/*/*/*/rule[contains(., 'Transform')]/@transform" use="."/>
<xsl:template match="/" mode="xsltname">
    <xsl:variable name="firstoutput">
        <xsl:call-template name="firstpass"/>
    </xsl:variable>
    <xsl:apply-templates select="mutate">            
        <xsl:with-param name="pr" select="exsl:node-set($firstoutput)/*"/>
    </xsl:apply-templates>
</xsl:template>
<xsl:template match="/*" name="firstpass">
    <dpXsltTransforms>
        <xsl:for-each select="/*/*/*/rule[contains(., 'Transform')]/@transform[generate-id()
                                   = generate-id(key('xsltkey',.)[1])]">
            <transform-dpPath>
                <xsl:value-of select="."/>
            </transform-dpPath>
        </xsl:for-each>
    </dpXsltTransforms>
</xsl:template>
<xsl:template match="mutate">
    <xsl:param name="pr"/>
    <services-xslt>            
        <xsl:for-each select="pr/transform-dpPath[contains(., 'local:///services/xslt/')]">
            <xslt-cognomen>
                <xsl:value-of select="substring(.,24)"/>
            </xslt-cognomen>
        </xsl:for-each>
    </services-xslt>
</xsl:template>
</xsl:stylesheet>"""

try:
    transformer = TransformerFactory.newInstance().newTransformer(StreamSource(StringReader(source_xform_xslt)))
    output_buffer = StringWriter()       
    transformer.transform(StreamSource(StringReader(source_xform_xml)), StreamResult(output_buffer))
    print output_buffer.buffer.toString()        
    return output_buffer.buffer.toString()   
except:                
    raise


if __name__ == '__main__':
    obtainservicexslts()

Выполнение командной строки

Если мы возьмем 'xml' и 'xslt' из скрипта, сохраним как 2 отдельных файла и выполним преобразование в XMLSPY, результат будет ниже.

Выполнение XMLSPY

Результат от XMLSPY желателен, и я не могу воспроизвести такое же поведение, используя свой код.

Еще один момент, который следует отметить, я использовал «exsl» как часть xslt. Не уверен, если это имеет значение

Кто-нибудь сталкивался с подобной проблемой и как ее решили?

Пожалуйста, киньте несколько указателей

Я готов изменить код в xslt или jython, чтобы добиться цели.


person Kpulaparthi    schedule 04.10.2017    source источник
comment
Первый и третий шаблоны нужны только для того, чтобы запутать людей? Кажется, эти режимы никогда не используются. Я получаю правильный результат с Saxon на xsltransform.net/ehVYZNQ или Xalan на xsltransform.net/gVhD8RS, поэтому это не похоже на XSLT и Java. Не знаете, что пошло не так, что происходит, когда вы пишете код Java вместо Jython? Вы получаете тот же результат, что и с Jython?   -  person Martin Honnen    schedule 04.10.2017
comment
@MartinHonnen, я не пробовал на Java, так как хочу сделать это только на Jython. Согласитесь, что первый и третий шаблон никогда не используются. Мне нужно это исправить. Спасибо, что поделились результатами Saxon и Xalan. Они аналогичны результатам XML SPY. Проблема не в XSLT. Это связано с тем, как Jython обрабатывает XML с помощью XSLT.   -  person Kpulaparthi    schedule 05.10.2017
comment
Поскольку преобразователь Jython по умолчанию, похоже, генерирует ошибочный вывод, моей первой рекомендацией было бы использовать другой заведомо исправный преобразователь. Если это не вариант, то мне кажется, что вам лучше всего попытаться упростить XSLT, чтобы, возможно, вырезать часть, о которую спотыкается Transformer по умолчанию.   -  person John Bollinger    schedule 05.10.2017
comment
Упрощения/изменения, которые вы можете внести, включают (*) удаление шаблонов, которые на самом деле не используются; (*) вместо использования generate-id() для идентификации экземпляров групп используйте объединение узлов и count(): ...@transform[count(. | key('xsltkey',.)[1]) = 1].   -  person John Bollinger    schedule 05.10.2017
comment
Или мы можем предположить, что вашему преобразователю не нравятся ключи, соответствующие узлам атрибутов. Поэтому вы можете попробовать определить свой ключ, чтобы вместо этого он соответствовал элементу, несущему атрибут, с соответствующими настройками в другом месте.   -  person John Bollinger    schedule 05.10.2017
comment
@JohnBollinger, поскольку изменение стандартного Transformer Jython не было для меня вариантом, я попробовал ваш [союз набора узлов] и [count ()], и это сработало. Большое спасибо, и, если возможно, не могли бы вы объяснить, в чем могла быть проблема с [generate-id()]   -  person Kpulaparthi    schedule 05.10.2017
comment
@Kpulaparthi, я могу только догадываться о режиме отказа generate-id(), но я предполагаю, что он возвращает разные значения для того, что должно было быть одним и тем же атрибутом узлов, поэтому ваши сравнения идентификаторов всегда терпели неудачу. То, что альтернатива, которую я предложил, работает, говорит мне, что оператор объединения действительно распознает, когда два выражения создают один и тот же узел, поэтому я думаю, что проблема, вероятно, специфична и локализована в generate-id().   -  person John Bollinger    schedule 05.10.2017