xslt是将文本转换为xml结构的好方法吗?
本文关键字:方法 结构 xml 文本 转换 xslt | 更新日期: 2023-09-27 18:15:19
我试图找到一个更好的解决方案来转换纯文本(但与预定义的长度为每个字段)到xml。例如,输入文本可以是"Testuser new york 10018",前11个字符为用户名,后12个字符为城市,后5个字符为邮政编码。所以我需要用预定义的字段长度从上面的字符串形成一个xml。
我在想两种方法
-
定义一个业务实体,并通过在输入文本上使用子字符串函数填充实体属性,然后将实体序列化为xml
-
预定义xml结构,使用xslt导航到每个节点并通过填充值
(XSLT) "isn't suitable for transforming from structured text to XML. "
和"XSLT
must
have XML as the input document"
**语句都是错误的
我在想两种方法
定义一个业务实体,并通过在输入文本上使用子字符串函数填充实体属性,然后将实体序列化为xml
预定义xml结构,使用xslt导航到每个节点,并通过在输入文本上使用子字符串函数填充值。
实际上,方法2很容易用XSLT完成:
。XSLT 1.0 :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*/text()" name="processLines">
<xsl:param name="pText" select="."/>
<xsl:if test="contains($pText, '
')">
<xsl:variable name="vLine" select=
"substring-before($pText, '
')"/>
<user>
<name>
<xsl:value-of select=
"translate(substring-before($vLine, ' '),'_',' ')"/>
</name>
<city>
<xsl:value-of select=
"translate(substring-before(substring-after($vLine, ' '),' '),
'_',
' '
)
"/>
</city>
<zipCode>
<xsl:value-of select=
"translate(substring-after(substring-after($vLine, ' '),' '),
'_',
' '
)
"/>
</zipCode>
</user>
<xsl:call-template name="processLines">
<xsl:with-param name="pText" select=
"substring-after($pText, '
')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
当将此转换应用于特殊格式的文本(包装在单个top元素中以使其格式良好——正如我们将在XSLT 2.0中看到的那样,不需要这样的包装)时:
<t>Testuser new_york 10018
usera seattle 98000
userb bellevue 98004
userb redmond 98052
</t>
产生想要的结果:
<user>
<name>Testuser</name>
<city>new york</city>
<zipCode>10018</zipCode>
</user>
<user>
<name>usera</name>
<city>seattle</city>
<zipCode>98000</zipCode>
</user>
<user>
<name>userb</name>
<city>bellevue</city>
<zipCode>98004</zipCode>
</user>
<user>
<name>userb</name>
<city>redmond</city>
<zipCode>98052</zipCode>
</user>
指出:
这只是一个演示如何完成任务的演示。这就是为什么我不处理固定宽度的字段(虽然会更容易),但空格分隔值。
任何值中包含的任何空格都以下划线(或我们选择的任何字符)的形式输入,我们知道这些字符永远不会成为任何值的一部分。在输出时,任何下划线都被转换为实空间。
二世。XSLT 2.0解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vText" select=
"unparsed-text('file:///c:/temp/delete/delete.txt')"/>
<xsl:variable name="vLines" select=
"tokenize($vText, '
?
')[normalize-space()]"/>
<xsl:template match="/">
<xsl:for-each select="$vLines">
<xsl:variable name="vFields" select=
"tokenize(., ' ')[normalize-space()]"/>
<user>
<name>
<xsl:sequence select="translate($vFields[1], '_',' ')"/>
</name>
<city>
<xsl:sequence select="translate($vFields[2], '_',' ')"/>
</city>
<zipCode>
<xsl:sequence select="translate($vFields[3], '_',' ')"/>
</zipCode>
</user>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当此转换应用于任何XML文档时(没有使用,实际上也不需要,因为在XSLT 2.0中不需要有源XML文档),如果文件C:'temp'delete'delete.txt
为,则:
Testuser new_york 10018
usera seattle 98000
userb bellevue 98004
userb redmond 98052
再次生成所需的正确结果:
<user>
<name>Testuser</name>
<city>new york</city>
<zipCode>10018</zipCode>
</user>
<user>
<name>usera</name>
<city>seattle</city>
<zipCode>98000</zipCode>
</user>
<user>
<name>userb</name>
<city>bellevue</city>
<zipCode>98004</zipCode>
</user>
<user>
<name>userb</name>
<city>redmond</city>
<zipCode>98052</zipCode>
</user>
指出:
使用标准XSLT 2.0函数
unparsed-text()
.使用标准XPath 2.0函数
tokenize()
.
:
大多数复杂的文本处理已经完全在XSLT中以工业方式完成。 FXSL库包含一个泛型LR(1)解析器和一个调整的YACC,该YACC生成xml格式的表,这些表是该泛型运行时LR(1)解析器的输入。
使用此工具,我成功地为JSON和XPath 2.0等复杂语言构建了解析器。
XSLT 2.0非常适合将结构化文本转换为XML。你可能想看看Stephanie Haupt和Maik Stuehrenberg在2010年发表的论文:
http://www.balisage.net/Proceedings/vol5/html/Haupt01/BalisageVol5-Haupt01.html还是我自己2008年的论文
http://www.saxonica.com/papers/ideadb - 1.1 -/- mhk - paper.xml
用于案例研究。
我通常不会尝试使用XSLT 1.0来完成这个任务,但正如Dimitre的回答所示,在简单的情况下可以完成。