xslt-2.0 - XML 到使用 XSLT_Complex 位置逻辑的固定长度文件 - 第 2 部分
问题描述
我们有一个需求,需要将 XML 转换为固定长度文件。第一条记录作为标题,之后我们有实际记录..从 2 条记录开始,我们需要应用下面提到的逻辑:
- 在长度 45 之后,考虑 10 个数字 0000001000,我们需要按照下表检查和替换的最后一个数字是多少。
- 我们需要在第 59 到第 74 位重复相同的逻辑。
- 第 77 到第 80 我们需要获取值 5152 并存储到一个变量中
我用第一个逻辑问了这个问题并得到了很棒的回答,现在我剩下第二个和第三个逻辑了
For Positive: (0000001000) - (000000100{)
{= 0
A = 1
B = 2
c = 3
D = 4
E = 5
F = 6
G = 7
H = 8
I = 9
请求任何人帮助我实现同样的目标,我已经提到了我从以前的答案中得到的 XSLT。谢谢
输入:
<ZR>
<INPUT>
<I_FIL>ERES</I_FIL>
</INPUT>
<TABLES>
<T_ER>
<item>
<DATA> HEADER1111111122222222333333344456</DATA>
</item>
<item>
<DATA>778944 D4E2 EA 1234567891 2018-11-060000001000EA 0000000000000100005152D04YA30TRE0000000XXXYYY 800{ Q 2018-11-05</DATA>
</item>
<item>
<DATA>987654 D4E2 EA 1987654321 2018-11-060000002001EA 0000000000000100005152D04YA30UUU0000000XXXLRB 100{ Q 2018-11-05</DATA>
</item>
.
.
.
.
.
.
.
.
<item>
<DATA>12345678912345678934562754378909726533297TRAILER</DATA>
</item>
</T_ER>
</TABLES>
</ZR>
XSLT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA" />
<xsl:value-of select="$break" />
<xsl:for-each select="ZR/TABLES/T_ER/item[position() != 1]">
<xsl:variable name="length" select="string-length(substring(DATA,0,46))" />
<xsl:variable name="tenNumbers" select="substring(DATA, ($length + 1),
10)"/>
<xsl:variable name="charToReplace" select="translate(substring($tenNumbers, string-length($tenNumbers), 1),'0123456789','{ABCDEFGHI')" />
<xsl:value-of select="concat(substring(DATA,0,46), substring(DATA, ($length + 1), 9), $charToReplace, substring(DATA,($length+11),(string-length(DATA) + 1)))"/>
<xsl:value-of select="$break" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
或者
<xsl:template match="/">
<xsl:value-of select="
ZR/TABLES/T_ER/item[1]/DATA,
ZR/TABLES/T_ER/item[position() > 1]/DATA/concat(
substring(., 1, 54),
substring('{ABCDEFGHI', number(substring(., 55, 1)) + 1, 1),
substring(., 56)
)" separator="
" />
</xsl:template>
预期输出:
HEADER1111111122222222333333344456
778944 D4E2 EA 1234567891 2018-11-06000000100{EA
000000000000010{005152D04YA30TRE0000000XXXYYY 800{ Q 2018-11-05
987654 D4E2 EA 1987654321 2018-11-06000000200AEA
000000000000010{005152D04YA30UUU0000000XXXLRB 100{ Q 2018-11-05
.
.
.
.
12345678912345678934562754378909726533297TRAILER
解决方案
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA" />
<xsl:value-of select="$break" />
<xsl:for-each select="ZR/TABLES/T_ER/item[position() != 1]">
<xsl:variable name="length" select="string-length(substring(DATA,0,46))" />
<xsl:variable name="tenNumbers" select="substring(DATA, ($length + 1), 10)" />
<xsl:variable name="sixteenNumbers" select="substring(DATA, (string-length(substring(DATA,0,59)) + 1), 16)" />
<xsl:variable name="firstCharToReplace" select="translate(substring($tenNumbers, string-length($tenNumbers), 1),'0123456789','{ABCDEFGHI')" />
<xsl:variable name="secondCharToReplace" select="translate(substring($sixteenNumbers, string-length($sixteenNumbers), 1),'0123456789','{ABCDEFGHI')" />
<xsl:choose>
<xsl:when test="string-length($tenNumbers) != 10">
<xsl:value-of select="concat(substring(DATA,0,46), substring(DATA, ($length + 1), 9))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(substring(DATA,0,46),
substring(DATA, ($length + 1), 9),
$firstCharToReplace,
substring(DATA,($length+11), 18),
$secondCharToReplace,
substring(DATA,($length+30),(string-length(DATA) + 1)))" />
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$break" />
<xsl:variable name="temp" select="substring(DATA,77,4)" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这取决于您要替换字符的条件。
如果它基于after EA
(根据评论),则解决方案会有所不同。
目前,我仅length
根据第 2 点和第 3 点来实现它。
http://xsltfiddle.liberty-development.net/6r5Gh38/1
编辑:
http://xsltfiddle.liberty-development.net/6r5Gh38/2
编辑2: 简要介绍评论中提到的要点:
1. <xsl:when test="string-length($tenNumbers) != 10">
添加此条件以删除出现在 last中的额外R<item>
。这意味着我们输入变量的 10 个数字是否实际上有 10 个数字。
在最后一种情况下,
<item>
<DATA>12345678912345678934562754378909726533297TRAILER</DATA>
</item>
我们在第 46 个字符之后没有得到 10 个数字。我们得到的比这少。这就是为两种不同情况分离输出的原因。
2. substring(DATA,0,46)
--> 匹配前 45 个字符778944 D4E2 EA 1234567891 2018-11-06
substring(DATA, ($length + 1), 9)
--> 将从第 46 个索引中获取 9 个字符来匹配000000100
$firstCharToReplace
--> 这将替换第 10 个字符作为您对第一个问题的要求,即{
substring(DATA,($length+11), 18)
--> 它将从第 (45+11) 个索引开始剩余的字符串到第 18 个匹配的字符EA 000000000000010
$secondCharToReplace
--> 这将替换 (45+11+18)= 74th character 作为您对第二个问题的要求,即{
substring(DATA,($length+30),(string-length(DATA) + 1))
--> 它从 (45+30)= 第 75 个字符开始到最后一个索引并给出005152D04YA30TRE0000000XXXYYY 800{ Q 2018-11-05
注意: 在您的情况下,字符串之间存在额外的制表符和空格。这就是为什么索引号已更改以匹配您的预期输出的原因。