我们有一个要求,其中需要将XML转换为固定长度文件。
第一个记录作为标题,然后有实际记录。从2个记录开始,我们需要应用下面提到的逻辑:
1.长度为45后,考虑10个数字0000001000,
最后一位,我们需要按照以下内容进行检查和替换
表格:
"For Positive Amount: (0000001000) - (000000100{)
{= 0
A = 1
B = 2
c = 3
D = 4
E = 5
F = 6
G = 7
H = 8
I = 9
我没有太多想法,所以创建了小型XSLT,要求任何人都可以提供帮助。
输入:
<?xml version='1.0' encoding='utf-8'?>
<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
0000000000000100001020D04YA30TRE0000000XXXYYY 300{ P 2018-11-05</DATA>
</item>
<item>
<DATA>987654 D4E2 EA 1987654321 2018-11-060000002001EA
0000000000000100001020D04YA30UUU0000000XXXLRB 100{ P 2018-11-05</DATA>
</item>
.
.
.
.
.
.
.
.
</T_ER>
</TABLES>
</ZR>
XSLT:
<?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:template>
</xsl:stylesheet>
预期输出:
HEADER1111111122222222333333344456
778944 D4E2 EA 1234567891 2018-11-06000000100{EA
0000000000000100001020D04YA30TRE0000000XXXYYY 300{ P 2018-11-05
987654 D4E2 EA 1987654321 2018-11-06000000200AEA
0000000000000100001020D04YA30UUU0000000XXXLRB 100{ P 2018-11-05
.
.
.
.
答案 0 :(得分:1)
好,使用函数string-length
,substring
和translate
来满足您的要求,可以通过以下方式实现:
<?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="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>
答案 1 :(得分:1)
您似乎只是想根据自己的地图替换第55个字符,因此可以执行此操作...
<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]/DATA">
<xsl:variable name="char" select="substring('{ABCDEFGHI', number(substring(., 55, 1)) + 1, 1)" />
<xsl:value-of select="concat(substring(., 1, 54), $char, substring(., 56))" />
<xsl:value-of select="$break" />
</xsl:for-each>
</xsl:template>
这在XSLT 1.0中有效。
XSLT 2.0解决方案可能就是这样...
<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>
在XSLT 3.0中,如果您想考虑使用两个或更多字符,则可以利用map
的优点是易于扩展:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:fn="http://www.w3.org/2005/xpath-functions" >
<xsl:output omit-xml-declaration="yes"/>
<xsl:param name="break" select="'
'" />
<xsl:variable name="chars" as="map(xs:string, xs:string)">
<xsl:map>
<xsl:map-entry key="'0'" select="'{'"/>
<xsl:map-entry key="'1'" select="'A'"/>
<xsl:map-entry key="'2'" select="'B'"/>
<xsl:map-entry key="'3'" select="'C'"/>
<xsl:map-entry key="'4'" select="'D'"/>
<xsl:map-entry key="'5'" select="'E'"/>
<xsl:map-entry key="'6'" select="'F'"/>
<xsl:map-entry key="'7'" select="'G'"/>
<xsl:map-entry key="'8'" select="'H'"/>
<xsl:map-entry key="'9'" select="'I'"/>
</xsl:map>
</xsl:variable>
<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), $chars(substring(., 55, 1)), substring(., 56))" separator="
" />
</xsl:template>
</xsl:stylesheet>
XSLT 3.0中可能存在更好的方法,因此希望Martin Honnen很快会说...。