use*_*671 6 xml xslt xslt-1.0 fixed-width
我需要帮助使用xsl样式表将此xml格式化为固定宽度的文本文件.我对xsl知之甚少,并且在网上找到的关于如何做到这一点的信息非常少.
基本上我需要这个xml
<?xml version="1.0" encoding="UTF-8"?>
<Report>
<table1>
<Detail_Collection>
<Detail>
<SSN>*********</SSN>
<DOB>1980/11/11</DOB>
<LastName>user</LastName>
<FirstName>test</FirstName>
<Date>2013/02/26</Date>
<Time>14233325</Time>
<CurrentStreetAddress1>53 MAIN STREET</CurrentStreetAddress1>
<CurrentCity>san diego</CurrentCity>
<CurrentState>CA</CurrentState>
</Detail_Collection>
</table1>
</Report>
Run Code Online (Sandbox Code Playgroud)
在这种格式中,所有都在同一行
*********19801111user test 201302261423332553 MAIN STREET san diego CA
Run Code Online (Sandbox Code Playgroud)
这些是固定宽度
FR TO
1 9 SSN
10 17 DOB
18 33 LastName
34 46 FirstName
47 54 Date
55 62 Time
63 90 CurrentStreetAddress1
91 115 CurrentCity
116 131 CurrentStat
Run Code Online (Sandbox Code Playgroud)
非常感谢所有帮助!提前致谢!
以下是(在我看来)lite更可靠和可维护的版本:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text" indent="no"/>
<xsl:variable name="some_spaces" select="' '" />
<xsl:template match="/">
<xsl:apply-templates select="//Detail_Collection/Detail" />
</xsl:template>
<xsl:template match="Detail_Collection/Detail">
<xsl:apply-templates mode="format" select="SSN">
<xsl:with-param name="width" select="number(9-1)"/>
</xsl:apply-templates>
<xsl:apply-templates mode="format_date" select="DOB">
<xsl:with-param name="width" select="number(17-10)"/>
</xsl:apply-templates>
<xsl:apply-templates mode="format" select="LastName">
<xsl:with-param name="width" select="number(33-18)"/>
</xsl:apply-templates>
<xsl:apply-templates mode="format" select="FirstName">
<xsl:with-param name="width" select="number(46-34)"/>
</xsl:apply-templates>
<xsl:apply-templates mode="format_date" select="Date">
<xsl:with-param name="width" select="number(54-47)"/>
</xsl:apply-templates>
<xsl:apply-templates mode="format" select="Time">
<xsl:with-param name="width" select="number(62-55)"/>
</xsl:apply-templates>
<xsl:apply-templates mode="format" select="CurrentStreetAddress1">
<xsl:with-param name="width" select="number(90-63)"/>
</xsl:apply-templates>
<xsl:apply-templates mode="format" select="CurrentCity">
<xsl:with-param name="width" select="number(115-91)"/>
</xsl:apply-templates>
<xsl:apply-templates mode="format" select="CurrentState">
<xsl:with-param name="width" select="number(131-116)"/>
</xsl:apply-templates>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="node()" mode ="format">
<xsl:param name="width" />
<xsl:value-of select="substring(concat(text(),$some_spaces ), 1, $width+1)"/>
</xsl:template>
<xsl:template match="node()" mode="format_date">
<xsl:param name="width" />
<xsl:value-of select="substring(concat(translate(text(),'/',''),$some_spaces ), 1, $width+1)"/>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
即使输入中的字段与请求的输出不一致,或者输入中缺少字段,它也会创建正确的输出.此外,它还认为有多个详细信息条目.
在XSLT 1.0中执行此操作的秘诀在于,您可以将"填充策略"与"子字符串策略"结合起来,将一段文本填充或剪切到所需的宽度.特别是,这种形式的XSLT指令:
substring(concat('value to pad or cut', ' '), 1, 5)
Run Code Online (Sandbox Code Playgroud)
... concat用于向字符串添加多个填充字符并substring用于限制整体宽度的位置很有用.话虽如此,这是一个XSLT 1.0解决方案,可以实现您的需求.
请注意,在您的预期输出中,某些字符宽度与您的要求不符; 例如,根据要求,<LastName>应该大小为16个字符,而你的输出似乎在13处削减它.那说,我相信我的解决方案输出你期望的.
当这个XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes" method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Detail">
<xsl:apply-templates />
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="SSN">
<xsl:value-of
select="substring(concat(., ' '), 1, 9)"/>
</xsl:template>
<xsl:template match="DOB">
<xsl:value-of
select="substring(concat(translate(., '/', ''), ' '), 1, 8)"/>
</xsl:template>
<xsl:template match="LastName">
<xsl:value-of
select="substring(concat(., ' '), 1, 16)"/>
</xsl:template>
<xsl:template match="FirstName">
<xsl:value-of
select="substring(concat(., ' '), 1, 13)"/>
</xsl:template>
<xsl:template match="Date">
<xsl:value-of
select="substring(concat(translate(., '/', ''), ' '), 1, 8)"/>
</xsl:template>
<xsl:template match="Time">
<xsl:value-of
select="substring(concat(., ' '), 1, 8)"/>
</xsl:template>
<xsl:template match="CurrentStreetAddress1">
<xsl:value-of
select="substring(concat(., ' '), 1, 28)"/>
</xsl:template>
<xsl:template match="CurrentCity">
<xsl:value-of
select="substring(concat(., ' '), 1, 25)"/>
</xsl:template>
<xsl:template match="CurrentStat">
<xsl:value-of
select="substring(concat(., ' '), 1, 15)"/>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
...针对提供的XML运行(</Detail>添加了以使文档格式正确):
<Report>
<table1>
<Detail_Collection>
<Detail>
<SSN>*********</SSN>
<DOB>1980/11/11</DOB>
<LastName>user</LastName>
<FirstName>test</FirstName>
<Date>2013/02/26</Date>
<Time>14233325</Time>
<CurrentStreetAddress1>53 MAIN STREET</CurrentStreetAddress1>
<CurrentCity>san diego</CurrentCity>
<CurrentState>CA</CurrentState>
</Detail>
</Detail_Collection>
</table1>
</Report>
Run Code Online (Sandbox Code Playgroud)
...产生了想要的结果:
*********19801111user test 201302261423332553 MAIN STREET san diego CA
Run Code Online (Sandbox Code Playgroud)