XSLT 使用 xslt 2.0 或更高版本将纯文本文件处理为 XML
Posted
技术标签:
【中文标题】XSLT 使用 xslt 2.0 或更高版本将纯文本文件处理为 XML【英文标题】:XSLT to process plain text file to XML using xslt 2.0 or higher 【发布时间】:2021-04-19 10:43:53 【问题描述】:我正在与使用“Workday”ERP 的客户合作。该 ERP 主要处理 XML、XSLT 和 XSD 脚本,但不处理其他编程语言来转换数据进出 ERP。
我有一个固定长度的文本文件(示例如下),我正在尝试将其转换为 XML 以便在我的代码中进行进一步处理。我一直使用 XSLT 将 xml 转换为 xml (OR) xml 转换为文本,但反之则不然。
您能否指导我或提供一个示例 XSLT(2.0 或 3.0)以将以下文本数据转换为目标 XML(如下)。
输入定长文件:(第一个字符为记录类型,X,H为表头,最后的T,F为尾。每条Employee记录以1条E记录开头,后接多条W记录和B记录(可选)) .
X T3.03Q2020320201029015631AACW2 xxxxxxx 2020xx 090420
H ZXCV 20200930 ABCABCA ABCABC
E ******13662 372022456 Tony B StarkS 99999 Heritage Pkwy zzzzzz MI48092 YNNNMS19960706 19720724 PM 99999 Heritage Pkwy zzzzzz MI48092
WW_SWW26 61322 1524206 1442835 1442835 0 0 0 0 0 0 215611 5342667 5073153 5073153 0 0 0 NN 0 0 N N 0000000000YYY 14 440 0 0 0 0 0 0N
WW_CITYR2665440 9192 972143 919215 919215 0 0 0 0 0 0 9192 972143 919215 919215 0 0 0 NN 0 0 N N 0000000000NYY 14 440 0 0 0 0 0 0N
BW_OASFEDERAL 93217 1524206 1503506 1503506 0 0 0 0 0 0 327181 5342667 5277117 5277117 0 0 0 NN 0 0 N N 0000000000YYY 14 440 0 0 0 0 0 0N
E ******10665 362022493 Thor S Asar 2323 Clyde Road Highzzzz MI48357 YNNNMS19990517 19760301 PM 2323 Clyde Road Highzzzz MI48357
WW_SWW26 61322 1524206 1442835 1442835 0 0 0 0 0 0 215611 5342667 5073153 5073153 0 0 0 NN 0 0 N N 0000000000YYY 14 440 0 0 0 0 0 0N
WW_CITYR2665440 9192 972143 919215 919215 0 0 0 0 0 0 9192 972143 919215 919215 0 0 0 NN 0 0 N N 0000000000NYY 14 440 0 0 0 0 0 0N
BW_OASFEDERAL 93217 1524206 1503506 1503506 0 0 0 0 0 0 327181 5342667 5277117 5277117 0 0 0 NN 0 0 N N 0000000000YYY 14 440 0 0 0 0 0 0N
BW_OASFEDERAL 93217 1524206 1503506 1503506 0 0 0 0 0 0 327181 5342667 5277117 5277117 0 0 0 NN 0 0 N N 0000000000YYY 14 440 0 0 0 0 0 0N
T 39384 1699589934
F 43442 1854024842
预期的 XMl 输出如下所示:
<?xml version='1.0' encoding='utf-8'?>
<File>
<X_Header></X_Header>
<H_Header></H_Header>
<All_Employees>
<Employee>
<E_record></E_record>
<W_record></W_record>
<W_record></W_record>
<W_record></W_record>
<B_record></B_record>
</Employee>
<Employee>
<E_record></E_record>
<W_record></W_record>
<W_record></W_record>
<W_record></W_record>
<B_record></B_record>
</Employee>
</All_Employees>
<T_Trailer></T_Trailer>
<F_Trailer></F_Trailer>
</File>
【问题讨论】:
在 XSLT 2 中,您可以使用unparsed-text
XPath 2 函数将文本文件读入字符串,在 XSLT 3 中,您还可以使用 unparsed-text-lines
作为函数,以在文本文件中读取表示线条的字符串序列。在这种情况下,您通常使用命名模板开始处理(例如,XSLT 2 中的 <xsl:template name="main">...</xsl:template>
或 XSLT 3 中使用预定义的 <xsl:template name="xsl:initial-template">...</xsl:template>
。要进一步分解字符串,请使用 tokenize
函数和/或 analyze-string
函数或xsl:analyze-string
指令。
【参考方案1】:
所以 XSLT 3 代码可以使用例如
<xsl:param name="lines" select="unparsed-text-lines('file.txt')"/>
<xsl:template match=".[. instance of xs:string]" mode="header">
<xsl:element name="substring(., 1, 1)_Header">
<xsl:apply-templates select="tokenize(., '\s+')" mode="data"/>
</xsl:element>
</xsl:template>
<xsl:template match=".[. instance of xs:string]" mode="trailer">
<xsl:element name="substring(., 1, 1)_Trailer">
<xsl:apply-templates select="tokenize(., '\s+')" mode="data"/>
</xsl:element>
</xsl:template>
<xsl:template match=".[. instance of xs:string]">
<xsl:element name="substring(., 1, 1)_Record">
<xsl:apply-templates select="tokenize(., '\s+')" mode="data"/>
</xsl:element>
</xsl:template>
<xsl:template match="." mode="data" expand-text="yes">
<Data>.</Data>
</xsl:template>
<xsl:template match="/" name="xsl:initial-template">
<File>
<xsl:apply-templates mode="header" select="$lines[starts-with(., 'H') or starts-with(., 'X')]"/>
<All_Employees>
<xsl:for-each-group select="$lines[not(matches(., '^[HXTF]'))]" group-starting-with=".[starts-with(., 'E')]">
<Employee>
<xsl:apply-templates select="current-group()"/>
</Employee>
</xsl:for-each-group>
</All_Employees>
<xsl:apply-templates mode="trailer" select="$lines[starts-with(., 'T') or starts-with(., 'F')]"/>
</File>
</xsl:template>
您尚未详细说明如何解析每一行,但您可以轻松调整标记化和模板。
【讨论】:
以上是关于XSLT 使用 xslt 2.0 或更高版本将纯文本文件处理为 XML的主要内容,如果未能解决你的问题,请参考以下文章
使用 XSLT 2.0/3.0 使用多个步骤将 CDATA 中的纯文本解析为 html。那里的一部分