#java #xslt #apache-fop
#java #xslt #apache-fop
Вопрос:
У меня есть файл xslt для преобразования XML-файла в PDF с помощью apache-fop. Но у меня нет всей информации о пространствах имен в моем xslt. Это зависит от xml. Я могу проанализировать XML-документ на Java и получить все пространства имен из xml. Но я не знаю, как я могу передать эти пространства имен из Java в мой файл xslt и как затем объявить его в <xsl:stylesheet>
теге. Возможно ли это?
Я не могу вставить свои оригинальные xslt и xml, потому что в них есть конфиденциальные данные, но я подготовил примеры файлов, чтобы показать мою проблему:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:OtherCompany xmlns:ns8="http://www.company.com/schema/SF/definition/type/test" xmlns:ns0="http://www.company.com/schema/SF/definition/type/a" xmlns:ns7="http://www.company.com/schema/SF/definition/type/b" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:Header>
<ns8:From>2018-01-01</ns8:From>
<ns8:To>2018-12-31</ns8:To>
<ns8:CheckDate>2019-03-28</ns8:CheckDate>
<ns7:Code sysCode="1">Report</ns7:Code>
<ns7:Type>1</ns7:Type>
</ns0:Header>
<ns0:Changes>
<ns7:I>
<ns8:AmountA>1499142.61</ns8:AmountA>
<ns8:AmountB>54979.16</ns8:AmountB>
</ns7:I>
<ns7:II>
<ns8:AmountA>3398983.19</ns8:AmountA>
<ns8:AmountB>1499142.61</ns8:AmountB>
</ns7:II>
<ns7:III>
<ns8:AmountA>3398983.19</ns8:AmountA>
<ns8:AmountB>1499142.61</ns8:AmountB>
</ns7:III>
</ns0:Changes>
</ns0:OtherCompany>
и xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="fo" xmlns:ns0="http://www.company.com/schema/SF/definition/type/a" xmlns:ns7="http://www.company.com/schema/SF/definition/type/b">
<xsl:param name="xmlPathPrefix"/>
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simpleA4" page-height="30cm" page-width="26cm" margin-top="2cm" margin-bottom="2cm" margin-left="1cm" margin-right="1cm">
<fo:region-body region-name="xsl-region-body" margin-top=".80in" margin-bottom=".50in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simpleA4">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="10pt" font-family="Arial">
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-width="12cm" xsl:use-attribute-sets="columnStyle"/>
<fo:table-column column-width="12cm" xsl:use-attribute-sets="columnStyle"/>
<fo:table-header>
<fo:table-row xsl:use-attribute-sets="columnStyle">
<fo:table-cell xsl:use-attribute-sets="centerCellStyle">
<fo:block font-weight="bold">Name</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="centerCellStyle">
<fo:block font-weight="bold">Value</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:apply-templates select="$xmlPathPrefix//*[not(contains(name(), 'Content'))]"/>
</fo:table-body>
</fo:table>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="$xmlPathPrefix//*[not(contains(name(), 'Content'))]">
<fo:table-row xsl:use-attribute-sets="columnStyle">
<fo:table-cell>
<fo:block>
<xsl:value-of select="sf:addSpaces(local-name(), sf:depth-of-node(.))"/>
</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="marginColumnStyle">
<fo:block>
<xsl:choose>
<xsl:when test="*">
<xsl:value-of select="''"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="current()"/>
</xsl:otherwise>
</xsl:choose>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>
Я хочу передать из java параметр xmlPathPrefix и использовать его в файле xslt в <xsl:template>
атрибуте соответствия
<xsl:template match="/$xmlPathPrefix/values">
или в xsl:apply-templates
выберите атрибут
<fo:table-body>
<xsl:apply-templates select="$xmlPathPrefix//*[not(contains(name(), 'Content'))]"/>
</fo:table-body>
Но я получаю следующую ошибку:
Введите ошибку оценки ($xmlPathPrefix) в xsl:apply-templates/@select в строке 38 столбца 75 test.xsl: XPTY0019: Требуемый тип элемента первого операнда ‘/’ — это node(); предоставленное значение u»ns0: OtherCompany/ns0:Changes …» является атомарным значением
Как я могу передать xmlPathPrefix из java и использовать его в моем xslt? Я хочу передать строку примера как xmlPathPrefix
«ns0: Другая компания / ns0: изменения»
Вторая проблема — это мое пространство имен, префикс пути может быть другим, но локальное имя всегда одно и то же, например, это может быть:
"ns0:OtherCompany/ns0:Changes"
"ns10:OtherCompany/ns15:Changes"
"companyType:OtherCompany/companyChanges:Changes"
или другие варианты. Когда у меня есть xslt, я должен объявить тег в <xsl:stylesheet>
примере ns0, ns10, CompanyType и т.д. Если я не объявлю это, я получу ошибку. Но я не знаю, какие пространства имен объявлены в моем xml. Как я могу передать это в xslt?
Пример, который я передаю
xmlPathPrefix: «ns10: OtherCompany /ns15:Изменения»
и пространства имен для этого: ns10 и ns15
Но я не знаю, как этого достичь.
Комментарии:
1. Покажите минимальный, но полный образец XML вместе с соответствующим XSLT и требуемым выводом, и я уверен, что мы сможем помочь. XSLT / XPath наверняка может читать / анализировать пространства имен в документе XML, не зная их, или создавать или копировать элементы в определенном пространстве имен.
2. @MartinHonnen Я завершил свой пост с примерами данных. Может быть, вы можете помочь мне сейчас?
Ответ №1:
Используете ли вы процессор XSLT 2, такой как Saxon 9? В вашем коде XSLT написано version="2.0"
. Если вы имеете дело с различными пространствами имен, то одним из способов в XSLT / XPath 2 и более поздних версиях является использование подстановочного знака *
для префикса пространства имен, например, *:OtherCompany/*:Changes
для выбора этих элементов в любом пространстве имен.
Для параметризации select
выражений вам нужно будет использовать процессор XSLT 3, такой как Saxon 9.8 или 9.9, и так называемые атрибуты тени, такие как _select
и статические параметры:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="prefix" as="xs:string" static="yes" select="'/*:root/*:foo'"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates _select="{$prefix}/*:bar"/>
</xsl:template>
<xsl:template match="*:bar">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle .liberty-development.net/ej9EGco
Я думаю, вам нужно было бы использовать программный интерфейс Saxon s9api для установки статических параметров.
Комментарии:
1. Большое спасибо, на данный момент все работает хорошо. Я отмечаю ваш ответ как «принимаю», но, возможно, мне понадобится помощь позже.