【发布时间】:2012-05-23 13:54:50
【问题描述】:
在 XSLT 中,有一个用于序列的 remove() 函数。给定一个序列和一个位置,它返回序列减去给定位置的项目。
问题是:如何在实际的 XSLT 文件中使用此函数?
我发现唯一提到的示例不仅仅是完全没有上下文的函数规范的反刍:http://books.google.com/books?id=W6SpffnfEPoC&pg=PA776&lpg=PA776&dq=xslt+%22remove+function%22&source=bl&ots=DQQrnXF_nB&sig=nrJtpEvYjBaZU0K8iAtdPTGUIbI&hl=en&sa=X&ei=QOq8T7aPDOyI6AHh-JBP&ved=0CEQQ6AEwAQ#v=onepage&q=xslt%20%22remove%20function%22&f=false
不幸的是,样式表示例位于第 777 和 778 页上,当然,这不包括在内。我不拥有那本书。
那么,有人有在实际样式表中使用remove() XSLT 函数的示例吗?
编辑:让我们提供一个更具体的例子,好吗?
我在 XSLT 中有一个序列。此序列由文本文件中的所有行组成。
<xsl:variable name="lines" select="tokenize(unparsed-text($filePath), '\r?\n')" />
这些行中的每一行都是一个记录...除了一个,它给了我记录数。所以我有以下代码来查找该行:
<xsl:variable name="recordCount">
<xsl:for-each select="$lines[position()]">
<xsl:variable name="i" select="position()" />
<xsl:analyze-string select="$lines[$i]" regex="RECORD COUNT = \d+">
<xsl:matching-substring>
<xsl:value-of select="replace($lines[$i], '[^0-9]', '')" />
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:for-each>
</xsl:variable>
在开始循环遍历这些行以获取所有实际记录之前,我执行了上述操作,因此我的目标是在找到时从$lines 序列中删除“记录计数”行。这样,当我循环抓取记录时,我不必每次询问“这实际上不是记录,而是记录计数行吗?你知道,我已经寻找并找到的那个东西吗? "
编辑 (2): 基于 Martin Honnen 的回答,我的最终 XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<!-- I want to produce an XML document. -->
<xsl:output method="xml" indent="yes" />
<!-- Path to input text file. -->
<xsl:param name="filePath" select="TestFile.txt" />
<!-- Regex in replace() removes leading and trailing blank space. -->
<xsl:variable name="text" select="replace(unparsed-text($filePath), '(^[\r\n]*\s*[\r\n]+)|([\r\n]+\s*[\r\n]*$)', '')" />
<!-- Regex in tokenize() sets the delimiter to be any blank space between record lines. -->
<!-- This effectively removes any blank lines. -->
<xsl:variable name="lines" select="tokenize($text, '[\r\n]+\s*[\r\n]*')" />
<!-- This finds the "RECORD COUNT = ?" line. -->
<xsl:variable name="recordCountIndex"
select="for $pos in 1 to count($lines) return $pos[matches($lines[$pos], 'RECORD COUNT = \d+')]" />
<!-- Regex in replace() strips everything that's not a number, leaving only the numeric count. -->
<!-- Example: "RECORD COUNT = 25" -> "25" -->
<xsl:variable name="recordCount" select="replace($lines[$recordCountIndex], '[^0-9]', '')" />
<xsl:template name="main">
<root>
<recordCount>
<!-- The record count value being inserted. -->
<xsl:value-of select="$recordCount" />
</recordCount>
<records>
<!-- Iterate over the $lines minus the line containing the record count. -->
<xsl:for-each select="remove($lines, $recordCountIndex)">
<!-- Items in each record, split by blank space. -->
<!-- Example: "a b c" -> "[a, b, c]" -->
<xsl:variable name="record" select="tokenize(., ' ')[position()]" />
<record>
<aThing>
<xsl:value-of select="$record[1]" />
</aThing>
<aDifferentThing>
<xsl:value-of select="$record[2]" />
</aDifferentThing>
<someStuff>
<xsl:value-of select="$record[3]" />
</someStuff>
</record>
</xsl:for-each>
</records>
</root>
</xsl:template>
</xsl:stylesheet>
【问题讨论】: