#xml #xslt #xslt-2.0
#xml #xslt #xslt-2.0
Вопрос:
Мне нужно разделить столбцы таблицы и создать новую таблицу на преобразованном xml.
Входной XML, который у меня есть:
<table frame="none">
<tgroup cols="9">
<colspec colname="column-0" colnum="1" colsep="1" rowsep="1" />
<colspec colname="column-1" colnum="2" colsep="1" rowsep="1" />
<colspec colname="column-2" colnum="3" colsep="1" rowsep="1" />
<colspec colname="column-3" colnum="4" colsep="1" rowsep="1" />
<colspec colname="column-4" colnum="5" colsep="1" rowsep="1" />
<colspec colname="column-5" colnum="6" colsep="1" rowsep="1" />
<colspec colname="column-6" colnum="7" colsep="1" rowsep="1" />
<colspec colname="column-7" colnum="8" colsep="1" rowsep="1" />
<colspec colname="column-8" colnum="9" colsep="1" rowsep="1" />
<thead>
<row>
<entry colname="column-0" colsep="1" rowsep="1" />
<entry colname="column-1" colsep="1" rowsep="1">
<p>
<b>AAAA</b>
</p>
</entry>
<entry colname="column-2" colsep="1" rowsep="1">
<p>
<b>BBBBBBBB</b>
[%]
</p>
</entry>
<entry colname="column-3" colsep="1" rowsep="1">
<p>
<b>CCCC</b>
</p>
</entry>
<entry colname="column-4" colsep="1" rowsep="1">
<p>
<b>DDDDDDD</b>
[%]
</p>
</entry>
<entry colname="column-5" colsep="1" rowsep="1">
<p>
<b>EEEE</b>
[%]
</p>
</entry>
<entry colname="column-6" colsep="1" rowsep="1">
<p>
<b>FFFF</b>
[%]
</p>
</entry>
<entry colname="column-7" colsep="1" rowsep="1">
<p>
<b>GGGG</b>
[%]
</p>
</entry>
<entry colname="column-8" colsep="1" rowsep="1">
<p>
<b>
HHH
<b>1</b>
</b>
</p>
</entry>
</row>
</thead>
<tbody>
<row>
<entry colname="column-0" colsep="1" rowsep="1">
<p>5°C/ambient RH 1.5 months</p>
</entry>
<entry colname="column-1" colsep="1" rowsep="1">
<p>101.6</p>
</entry>
<entry colname="column-2" colsep="1" rowsep="1">
<p>amp;<0.2</p>
</entry>
<entry colname="column-3" colsep="1" rowsep="1">
<p>0.1</p>
</entry>
<entry colname="column-4" colsep="1" rowsep="1">
<p>0.2</p>
</entry>
<entry colname="column-5" colsep="1" rowsep="1">
<p>0.2</p>
</entry>
<entry colname="column-6" colsep="1" rowsep="1">
<p>0.2</p>
</entry>
<entry colname="column-7" colsep="1" rowsep="1">
<p>0.1</p>
</entry>
<entry colname="column-8" colsep="1" rowsep="1">
<p>0.6</p>
</entry>
</row>
</tbody>
</tgroup>
</table>
Необходимо разделить входной xml на 3 xml (Colspec от 0 до 2, от 3 до 5, от 6 до 8), например, 3 colspec, 3 строки, 3 записи.
Первый XML:
<table frame="none">
<tgroup cols="9">
<colspec colname="column-0" colnum="1" colsep="1" rowsep="1" />
<colspec colname="column-1" colnum="2" colsep="1" rowsep="1" />
<colspec colname="column-2" colnum="3" colsep="1" rowsep="1" />
<thead>
<row>
<entry colname="column-0" colsep="1" rowsep="1" />
<entry colname="column-1" colsep="1" rowsep="1">
<p>
<b>AAAA</b>
</p>
</entry>
<entry colname="column-2" colsep="1" rowsep="1">
<p>
<b>BBBBBBBB</b>
[%]
</p>
</entry>
</row>
</thead>
<tbody>
<row>
<entry colname="column-0" colsep="1" rowsep="1">
<p>5°C/ambient RH 1.5 months</p>
</entry>
<entry colname="column-1" colsep="1" rowsep="1">
<p>101.6</p>
</entry>
<entry colname="column-2" colsep="1" rowsep="1">
<p>amp;<0.2</p>
</entry>
</row>
</tbody>
</tgroup>
</table>
Например, мне нужны еще два выходных xml для colspec с 3 по 5 и с 6 по 8.
XSL я пробовал:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="node()|@*" />
<xsl:result-document href="file:///C://xslttransform//table3.xml">
<xsl:apply-templates select="node()|@*" />
<xsl:apply-templates select="/topic/body/table/tgroup/colspec" />
<xsl:apply-templates select="/topic/body/table/tgroup/thead" />
<xsl:apply-templates select="/topic/body/table/tgroup/tbody" />
</xsl:result-document>
<xsl:result-document href="file:///C://xslttransform//table2.xml">
<xsl:apply-templates select="node()|@*" />
</xsl:result-document>
<xsl:result-document href="file:///C://xslttransform//table1.xml">
<xsl:apply-templates select="node()|@*" />
</xsl:result-document>
</xsl:template>
<xsl:template match="/topic/body/table/tgroup/colspec">
<xsl:message>Test11</xsl:message>
<xsl:if test=".[@colname='column-0']">
<xsl:message>Test22</xsl:message>
<xsl:variable name="columnfontoId">
<xsl:value-of select="./@id" />
</xsl:variable>
<colspec colname="column-0" colnum="1" colsep="1" id="{$columnfontoId}" rowsep="1" />
</xsl:if>
<xsl:if test=".[@colname='column-1']">
<xsl:message>Test22</xsl:message>
<xsl:variable name="columnfontoId">
<xsl:value-of select="./@id" />
</xsl:variable>
<colspec colname="column-1" colnum="2" colsep="1" id="{$columnfontoId}" rowsep="1" />
</xsl:if>
<xsl:if test=".[@colname='column-2']">
<xsl:message>Test22</xsl:message>
<xsl:variable name="columnfontoId">
<xsl:value-of select="./@id" />
</xsl:variable>
<colspec colname="column-2" colnum="3" colsep="1" id="{$columnfontoId}" rowsep="1" />
</xsl:if>
</xsl:template>
<xsl:template match="/topic/body/table/tgroup/thead">
<xsl:variable name="columnfontoId">
<xsl:value-of select="./@id" />
</xsl:variable>
<thead id="{$columnfontoId}">
<xsl:for-each select="row">
<xsl:variable name="columnfontoId">
<xsl:value-of select="./@id" />
</xsl:variable>
<row id="{$columnfontoId}">
<xsl:for-each select="entry">
<xsl:if test=".[@colname='column-0' or @colname='column-1' or @colname='column-2']">
<xsl:message>Test333</xsl:message>
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</row>
</xsl:for-each>
</thead>
</xsl:template>
<xsl:template match="/topic/body/table/tgroup/tbody">
<xsl:variable name="columnfontoId">
<xsl:value-of select="./@id" />
</xsl:variable>
<tbody id="{$columnfontoId}">
<xsl:for-each select="row">
<xsl:variable name="columnfontoId">
<xsl:value-of select="./@id" />
</xsl:variable>
<row id="{$columnfontoId}">
<xsl:for-each select="entry">
<xsl:if test=".[@colname='column-0' or @colname='column-1' or @colname='column-2']">
<xsl:message>Test333</xsl:message>
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</row>
</xsl:for-each>
</tbody>
</xsl:template>
</xsl:stylesheet>
Ответ №1:
Разделение можно выполнить следующим образом:
<?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:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:param name="block-size" as="xs:integer" select="3"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="table">
<xsl:for-each-group select="tgroup/colspec" group-adjacent="(position() - 1) idiv $block-size">
<xsl:apply-templates select="../.." mode="split"/>
</xsl:for-each-group>
</xsl:template>
<xsl:mode name="split" on-no-match="shallow-copy"/>
<xsl:template match="colspec | entry" mode="split">
<xsl:if test="@colname = current-group()/@colname">
<xsl:next-match/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle .liberty-development.net/jxNakAK
Для вывода каждой результирующей таблицы в отдельный файл измените шаблон для table
в режиме без имени и добавьте один для table
в split
режиме:
<xsl:template match="table">
<xsl:for-each-group select="tgroup/colspec" group-adjacent="(position() - 1) idiv $block-size">
<xsl:apply-templates select="../.." mode="split">
<xsl:with-param name="pos" select="position()"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:template>
<xsl:mode name="split" on-no-match="shallow-copy"/>
<xsl:template match="table" mode="split">
<xsl:param name="pos"/>
<xsl:result-document href="table-{$pos}.xml">
<xsl:next-match/>
</xsl:result-document>
</xsl:template>