我有这样的XML
<?xml version="1.0" encoding="UTF-8"?>
<Report>
<table1>
<Detail_Collection>
<Detail>
<ReceiptNo>RN12345678</ReceiptNo>
<ReceiptDate>1980/11/11</ReceiptDate>
<LastName>Dela Cruz</LastName>
<FirstName>Juan</FirstName>
<PurchaseDetails>
<Item>Wood</Item>
<Price>25.65</Price>
<Quantity>2</Quantity>
</PurchaseDetails>
<PurchaseDetails>
<Item>Axe</Item>
<Price>50.56</Price>
<Quantity>5</Quantity>
</PurchaseDetails>
</Detail>
</Detail_Collection>
</table1>
</Report>
我需要使用XSLT 1.0将其转换为平面文本文件
我发现了这个很好的解决方案
<?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>
但问题是我必须根据其数据类型格式化每个细节,如下所示
字母数字 - 应该是30个字符,右边是空格
数字(无符号) - 应该剩下15个字符,用零填充 例如000000000012345
数字(签名) - 应该剩下15个字符,用零填充 如果否定应该表示N&#39; N&#39;例如N00000000012345
从我的XML文件中输出应该是:
RN12345678 19801111Dela Cruz Juan Wood 000000000002565000000000000002
RN12345678 19801111Dela Cruz Juan Axe 000000000005056000000000000005
例如价格是负面的
RN12345678 19801111Dela Cruz Juan Wood N00000000002565000000000000002
RN12345678 19801111Dela Cruz Juan Axe N00000000005056000000000000005
顺便说一下,我有一些字符有300个字符(如填充物)所以我不知道我是否需要在变量some_spaces中放置300多个空格
日期应为8个字符YYYYMMDD。
我有一个模板即时使用,但不知道如何使用&#39; N&#39;对于否定的,以及如何根据要求格式化日期。
以下是模板:
<xsl:template name="prepend-pad">
<!-- recursive template to right justify and prepend the value with whatever padChar is passed in -->
<xsl:param name="padChar" />
<xsl:param name="padVar" />
<xsl:param name="length" />
<xsl:choose>
<xsl:when test="string-length($padVar) < $length">
<xsl:call-template name="prepend-pad">
<xsl:with-param name="padChar" select="$padChar"/>
<xsl:with-param name="padVar" select="concat($padChar,$padVar)"/>
<xsl:with-param name="length" select="$length"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($padVar,string-length($padVar) - $length + 1)" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
由于
答案 0 :(得分:1)
怎么样:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>
<xsl:variable name="spaces" select="' '"/>
<xsl:template match="/">
<xsl:for-each select="Report/table1/Detail_Collection/Detail/PurchaseDetails">
<xsl:apply-templates select="../ReceiptNo"/>
<xsl:apply-templates select="../ReceiptDate"/>
<xsl:apply-templates select="../LastName"/>
<xsl:apply-templates select="../FirstName"/>
<xsl:apply-templates select="Item"/>
<xsl:call-template name="format-number">
<xsl:with-param name="number" select="100 * Price"/>
</xsl:call-template>
<xsl:call-template name="format-number">
<xsl:with-param name="number" select="Quantity"/>
</xsl:call-template>
<xsl:if test="position()!=last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="ReceiptNo | LastName | FirstName | Item">
<xsl:value-of select="substring(concat(., $spaces), 1, 30)"/>
</xsl:template>
<xsl:template match="ReceiptDate">
<xsl:value-of select="translate(., '/', '')"/>
</xsl:template>
<xsl:template name="format-number">
<xsl:param name="number" select="0"/>
<xsl:choose>
<xsl:when test="$number >= 0">
<xsl:value-of select="format-number($number, '000000000000000')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="format-number(-$number, 'N00000000000000')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
恐怕我不明白这一部分:
顺便说一下,我有一些300字符的字段(比如a 填充物)所以我不知道我是否需要在变量中放置300多个空格 some_spaces
要在结果行中插入300个空格,建议您使用:
<xsl:text> (300 spaces here) </xsl:text>
可以使用命名模板动态生成任意数量的空格,但由于您需要一个常数,我无法看到它的任何优势。
关于它将以MM / dd / yyyy给我的日期,我需要 将其格式化为yyyyMMdd,对不起我提供的错误样本数据。
如果是这样,请将与日期字段匹配的模板更改为:
<xsl:template match="ReceiptDate">
<xsl:value-of select="concat(substring(., 7, 4), substring(., 1, 2), substring(., 4, 2))"/>
</xsl:template>
答案 1 :(得分:0)
如评论中所述,您的XSL与您提供的XML几乎没有关系。 因此,根据对平面文本文件的模糊要求并使用填充格式化数据,我做了一些猜测,并提出了以下内容。
<?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:for-each select="PurchaseDetails">
<xsl:call-template name="format">
<xsl:with-param name="textnode" select="../LastName"/>
<xsl:with-param name="width" select="number(33-18)"/>
<xsl:with-param name="type" select="string('A')"/>
</xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="format">
<xsl:with-param name="textnode" select="../FirstName"/>
<xsl:with-param name="width" select="number(46-34)"/>
<xsl:with-param name="type" select="string('A')"/>
</xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="format">
<xsl:with-param name="textnode" select="../ReceiptDate"/>
<xsl:with-param name="width" select="number(54-45)"/>
<xsl:with-param name="type" select="string('A')"/>
</xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="format">
<xsl:with-param name="textnode" select="Item"/>
<xsl:with-param name="width" select="number(54-45)"/>
<xsl:with-param name="type" select="string('A')"/>
</xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="format">
<xsl:with-param name="textnode" select="Quantity"/>
<xsl:with-param name="width" select="number(54-45)"/>
<xsl:with-param name="type" select="string('N')"/>
</xsl:call-template>
<xsl:call-template name="format">
<xsl:with-param name="textnode" select="Price"/>
<xsl:with-param name="width" select="number(54-45)"/>
<xsl:with-param name="type" select="string('N')"/>
</xsl:call-template>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template name="format">
<xsl:param name="width"/>
<xsl:param name="textnode"/>
<xsl:param name="type"/>
<xsl:variable name="leader_padding">
<xsl:choose>
<xsl:when test="$type='N' or $type='S'">
<xsl:value-of select="translate($some_spaces,' ','0')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$some_spaces"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="bigstring" select="concat($leader_padding,$textnode)"/>
<xsl:variable name="truncatedstring" select="substring($bigstring,string-length($bigstring)-$width)"/>
<xsl:choose>
<xsl:when test="$type='A'">
<xsl:text> </xsl:text>
</xsl:when>
<xsl:when test="$type='N' or ($type='S' and number($textnode >= 0))">
<xsl:text>0</xsl:text>
</xsl:when>
<xsl:otherwise>
<!-- type must be S and value must be negative -->
<xsl:text>N</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$truncatedstring"/>
</xsl:template>
</xsl:stylesheet>
当针对输入的xml文件运行时会生成:
Dela Cruz, Juan, 1980/11/11, Wood,0000000000200000025.65
Dela Cruz, Juan, 1980/11/11, Axe,0000000000500000050.56
这里有两行,因为输入格式不是很平坦。所以我选择每个购买项目一行。