У меня есть файл .ods, и я хочу получить доступ к значениям table-cells в table-rows по значению первого столбца для данной строки. Так что их направление в моем случае.
Итак, расчетная таблица выглядит так:
First_Name | Last_Name
Peter | Parker
Emma | Stone
...
Вот мой файл xslt-export-filter:
SuperBasicExportFilter.xslt
<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:stylesheet
version = "1.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:table = "urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:text = "urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"
exclude-result-prefixes = "table text office"
>
<xsl:output
method = "xml"
indent = "yes"
encoding = "UTF-8"
omit-xml-declaration = "no"
/>
<xsl:template match = "/">
<xsl:variable name = "columnHeadings">
<xsl:for-each select = "//table:table/table:table-row[not(preceding::table:table-row)]//table:table-cell">
<xsl:element name = "heading">
<xsl:attribute name = "name" select = "text:p" />
<xsl:value-of select = "position()" />
</xsl:element>
</xsl:for-each>
</xsl:variable>
<html>
<body>
<h1>Hello</h1>
<xsl:message>columnHeadings: <xsl:value-of select = "$columnHeadings" /></xsl:message>
<table>
<xsl:for-each select = "//table:table/table:table-row">
<xsl:if test = "position() > 1">
<tr>
<td>
First Column Value
<xsl:value-of select = "table:table-cell[1]/text:p" />
<!-- <xsl:value-of select = "table:table-cell[$columnHeadings/heading[@name='First_Name']]/text:p" /> -->
</td>
<td>
Second Column Value
<xsl:value-of select = "table:table-cell[2]/text:p" />
<!-- <xsl:value-of select = "table:table-cell[$columnHeadings/heading[@name='Last_Name']]/text:p" /> -->
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Сообщение показывает "columnHeadings: 1234567891011121314" и так далее. Таким образом, он правильно устанавливает значения позиции.
Я попытался получить значения на основе атрибута «имя» в элементе «заголовок». Но я никак не могу получить значения по отдельности. Кажется, я не могу использовать $columnHeadings с любым выражением XPath. Он просто возвращает «Оценка Xpath не дала результата».
Я пытался
<xsl:variable name = "columnHeadingsNode" select = "document('')//xsl:variable[@name = 'columnHeadings']" />
, чтобы затем получить значениеxsl:key
, например <xsl:key name = "columnHeadings" match = "//table:table/table:table-row[not(preceding::table:table-row)]//table:table-cell" use = "text:p" />
, но таким образом я не могу получить к нему доступ на основе «имени»Какие еще вещи я могу попытаться получить доступ к содержимому переменной с выражением xpath?
Можно ли вообще получить доступ к таким значениям, как table:table-cell[$columnHeadings/heading[@name='Last_Name']]?
Ответы на комментарии:
Какой процессор XSLT вы используете?
Я использую то, что использует libreoffice 7.4.5.1. Могу ли я это изменить? xsl:vendor — «libxslt», а версия — «1.0» в соответствии со значениями <xsl:value-of select = "system-property('xsl:vendor')"/> и xsl:version.
Вы получаете сообщение об ошибке <xsl:attribute name = "name" select = "text:p" />?
Я на самом деле нет, почему-то. Тест проходит без ошибок. Я получаю новую вкладку браузера с созданным выводом xml и без ошибок.
Я попытался поставить галочку «Фильтру требуется процессор XSLT 2.0», но тогда я больше не могу тестировать фильтр и не получаю никаких результатов.
Какова общая цель этого упражнения?
Я хочу иметь возможность выбирать значения в столбцах по соответствующему заголовку столбца, а не по индексу, потому что я хочу сделать его максимально переносимым. По крайней мере, я думаю, что это помогло бы достичь этой цели. У меня 184 столбца. Я полагаю, что имена столбцов не изменятся с такой вероятностью, как индекс столбца.
Вы получаете сообщение об ошибке <xsl:attribute name = "name" select = "text:p" />? Любой процессор XSLT 1.0 с version = "1.0" должен выдавать ошибку, поскольку XSLT 1.0 не разрешает атрибут select для xsl:attribute.
Вы можете посмотреть на stackoverflow.com/q/75514330/3016153. Обратите внимание, что процессор libxslt поддерживает ряд функций расширения, в том числе str:tokenize().
Намерение <xsl:attribute name = "name" select = "text:p" /> не может создать атрибут со значением в XSLT 1; это должно вызвать ошибку, но кажется, что ваш XSLT-процессор игнорирует select.
Поэтому постарайтесь
<xsl:attribute name = "name">
<xsl:value-of select = "text:p"/>
</xsl:attribute>
Вместо.
Таким образом, я бы подумал, что, например. <xsl:variable name = "columnHeadings-ns" select = "exsl:node-set($columnHeadings)" xmlns:exsl = "http://exslt.org/common"/> должен позволить вам использовать, например. <xsl:value-of select = "table:table-cell[$columnHeadings-ns/heading[@name='First_Name']]/text:p"/>.
Мне пришлось обернуть индекс из $columnHeadings в вызов number вот так <xsl:value-of select = "table:table-cell[number($columnHeadings-ns/heading[@name='First_Name'])]/text:p"/>. Я предполагаю, что функция node-set преобразовала его в строку.
С процессором XSLT 1.0 ваша переменная представляет собой фрагмент дерева результатов (RTF), либо переключитесь на процессор XSLT 2 или 3 (например, Saxon HE (последняя стабильная версия 11.5)) или узнайте, какой процессор XSLT 1.0 вы используете и какой тип Функция расширения, такая как exsl:node-set, поддерживает преобразование фрагмента результирующего дерева в набор узлов.