这可以用常规 XSL 完成吗?
是的,而且 XSLT 2.0 提供了比 XSLT 1.0 更多的工具来处理文本。XSLT 中实现了非常复杂的文本处理,包括通用 LR(1) 解析器,用于构建特定语法的解析器,例如 JSON和 XPath。
特别是,了解unparsed-text()
各种字符串函数,包括允许使用正则表达式(matches()
、tokenize()
和replace()
)的函数以及<xsl:analyze-string>
指令。
XSLT 1.0 也有字符串函数(由 XPath 1.0 提供),但是它缺少正则表达式能力/函数,并且没有像 XSLT 2.0 函数这样的东西unparsed-text()
。最有用的 XPath 1.0 字符串函数包括:substring()
, substring-before()
, substring-after()
, starts-with()
, string-length()
, concat()
, 尤其是translate()
函数。
正如 Mads Hansen 在他的回答中解释的那样,可以通过使用 DTD 中的实体来“读取”文件。另一种方法是在启动转换的程序中读取文件,然后将文件的内容作为字符串参数传递给转换。
更新:OP现在提供了具体数据,因此可以提供完整的解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vText" select=
"unparsed-text('file:///c:/temp/delete/test.ini')"/>
<xsl:variable name="vLines" as="xs:string*" select=
"tokenize($vText, '
?
')[.]"/>
<xsl:variable name="vLineCnt" select="count($vLines)"/>
<xsl:variable name="vSectLinesInds" as="xs:integer*" select=
"for $i in 1 to $vLineCnt
return
if(starts-with(normalize-space($vLines[$i]), '['))
then $i
else ()
"/>
<xsl:variable name="vSectCnt" select="count($vSectLinesInds)"/>
<xsl:template match="/">
<xsl:for-each select="$vSectLinesInds">
<xsl:variable name="vPos" select="position()"/>
<xsl:variable name="vInd" as="xs:integer" select="."/>
<xsl:variable name="vthisLine" as="xs:string"
select="$vLines[$vInd]"/>
<xsl:variable name="vNextSectInd" select=
"if($vPos eq $vSectCnt)
then
$vLineCnt +1
else
$vSectLinesInds[$vPos +1]
"/>
<xsl:variable name="vInnerLines" select=
"$vLines
[position() gt current()
and
position() lt $vNextSectInd
]
"/>
<xsl:variable name="vName" select=
"tokenize($vthisLine, '\[|\]')[2]"/>
<xsl:element name="{$vName}">
<xsl:for-each select="$vInnerLines">
<xsl:variable name="vInnerParts" select=
"tokenize(., '[ ]*=[ ]*')"/>
<xsl:element name="{$vInnerParts[1]}">
<xsl:value-of select="$vInnerParts[2]"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当此转换应用于任何 XML 文档(未使用)并且该文件 C:\temp\delete\test.ini
具有以下内容时:
[section1]
option1 = values1
option2 = values2
option3 = values3
option4 = values4
option5 = values5
[section2]
option1 = values1
option2 = values2
option3 = values3
option4 = values4
option5 = values5
[section3]
option1 = values1
option2 = values2
option3 = values3
option4 = values4
option5 = values5
产生了想要的正确结果:
<section1>
<option1>values1</option1>
<option2>values2</option2>
<option3>values3</option3>
<option4>values4</option4>
<option5>values5</option5>
</section1>
<section2>
<option1>values1</option1>
<option2>values2</option2>
<option3>values3</option3>
<option4>values4</option4>
<option5>values5</option5>
</section2>
<section3>
<option1>values1</option1>
<option2>values2</option2>
<option3>values3</option3>
<option4>values4</option4>
<option5>values5</option5>
</section3>