首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSLT -从文本中写入元素,然后计数节点并向父节点添加属性。

XSLT -从文本中写入元素,然后计数节点并向父节点添加属性。
EN

Stack Overflow用户
提问于 2015-08-26 15:36:42
回答 1查看 419关注 0票数 0

我正在从csv文件中读取数据,并将结果添加到DITA的精简版本的文件中的一个表中。

原始的DITA文件除其他外包括:

代码语言:javascript
复制
<para>Put table here.</para>

文本输入如下:

代码语言:javascript
复制
row1col1,row1col2,row1col3,row1col4,ro1col5,
row2col1,row2col2,row2col3,,row2col5
row3col1,,row3col3,row3col4,
row4col1,row4col2,,row4col4

我对XSLT的尝试是:

代码语言:javascript
复制
<?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:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no" doctype-system="myDTD.dtd" />

<!-- use this file on an empty chapter file -->
<!-- make sure the input file is a csv file  -->

    <!-- Edit these parameters if necessary. -->
    <!-- don't forget the single-quote inside double-quote in the select statements below -->
    <xsl:param name="text-encoding" as="xs:string" select="'iso-8859-1'"/>
    <!-- csv file -->
    <xsl:param name="text-uri" as="xs:string" select="'input.csv'"/> <!--change to rename input file-->


<!--Identity template, provides default behavior that copies all content into the output -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- Load csv file as a table -->
    <xsl:template match="para[.='Put table here.']">
        <xsl:element name="table">
            <xsl:attribute name="outputclass">horizontal</xsl:attribute>
            <xsl:attribute name="placement">default</xsl:attribute>
            <xsl:element name="tgroup">
                <!--
                <xsl:attribute name="cols">6</xsl:attribute> -->
                <!-- I know the following doesn't work, but to give you an 
                     idea of what I'm looking for - hardcoding as above 
                     works ok. -->
                <xsl:attribute name="cols">
                    <xsl:value-of select="max(count(tbody/row/entry))"/>
                </xsl:attribute>
                <xsl:attribute name="format">Horizontal</xsl:attribute>
                <xsl:element name="tabletitle">Enter title here</xsl:element>

                <xsl:element name="tbody">
                   <xsl:variable name="input" select="unparsed-text($text-uri, $text-encoding)"/>
                    <xsl:for-each select="tokenize($input, '\n')">

                        <xsl:element name="row">
                            <xsl:for-each select="tokenize(., ',')">

                                <xsl:element name="entry">
                                    <xsl:element name="para">
                                        <xsl:value-of select=". "/>
                                    </xsl:element>
                                </xsl:element>

                            </xsl:for-each>
                        </xsl:element>

                    </xsl:for-each>
                </xsl:element>

            </xsl:element>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

这产生了这个输出(部分),这几乎就是我想要的:

代码语言:javascript
复制
                <table outputclass="horizontal" placement="default">
                    <tgroup cols="0" format="Horizontal">
                        <tabletitle>Enter title here</tabletitle>
                        <tbody>
                            <row>
                                <entry>
                                    <para>row1col1</para>
                                </entry>
                                <entry>
                                    <para>row1col2</para>
                                </entry>
                                <entry>
                                    <para>row1col3</para>
                                </entry>
                                <entry>
                                    <para>row1col4</para>
                                </entry>
                                <entry>
                                    <para>ro1col5</para>
                                </entry>
                                <entry>
                                    <para>
</para>
                                </entry>
                            </row>

.等等..。

当然,我想要

代码语言:javascript
复制
<tgroup cols="0" >

标记将是

代码语言:javascript
复制
<tgroup cols="6"  >

如果我硬编码6,我就能得到我想要的。有什么方法可以动态地做到这一点吗?

非常感谢你的帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-26 15:47:07

因为您在XSLT2.0中,所以可以通过将表标记存储在一个变量中,然后在将其全部发送到输出之前计算出cols号。

代码语言:javascript
复制
            <xsl:element name="tgroup">

              <xsl:variable name="table">
                <xsl:element name="tabletitle">Enter title here</xsl:element>

                <xsl:element name="tbody">
                   <xsl:variable name="input" select="unparsed-text($text-uri, $text-encoding)"/>
                    <xsl:for-each select="tokenize($input, '\n')">

                        <xsl:element name="row">
                            <xsl:for-each select="tokenize(., ',')">

                                <xsl:element name="entry">
                                    <xsl:element name="para">
                                        <xsl:value-of select=". "/>
                                    </xsl:element>
                                </xsl:element>

                            </xsl:for-each>
                        </xsl:element>

                    </xsl:for-each>
                </xsl:element>
              </xsl:variable>

              <xsl:attribute name="cols">
                <xsl:value-of select="max($table/tbody/row/count(entry))"/>
              </xsl:attribute>
              <xsl:attribute name="format">Horizontal</xsl:attribute>
              <xsl:sequence select="$table/*" />
            </xsl:element>

注意我对您的max表达式所做的更改--您最初的方法是

代码语言:javascript
复制
max(count($table/tbody/row/entry))

无法工作,因为count(tbody/row/entry)是单个数字,表中所有行的条目元素总数。相反,你需要

代码语言:javascript
复制
max($table/tbody/row/count(entry))

它创建一个数字序列(每一行一个,数字是该行中条目的计数),然后在该序列中找到最高的数字。

顺便说一句,当您有固定的元素名时,如果使用文字结果元素而不是xsl:element,您可能会发现它更易读:

代码语言:javascript
复制
            <xsl:variable name="table">
                <tabletitle>Enter title here</tabletitle>

                <tbody>
                   <xsl:variable name="input" select="unparsed-text($text-uri, $text-encoding)"/>
                    <xsl:for-each select="tokenize($input, '\n')">

                        <row>
                            <xsl:for-each select="tokenize(., ',')">

                                <entry>
                                    <para>
                                        <xsl:value-of select=". "/>
                                    </para>
                                </entry>

                            </xsl:for-each>
                        </row>

                    </xsl:for-each>
                </tbody>
            </xsl:variable>

            <tgroup cols="{max($table/tbody/row/count(entry))}" format="Horizontal">
              <xsl:sequence select="$table/*" />
            </tgroup>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32230918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档