我需要使用XSLT将XML转换为Text。我得到的输出包含一个没有分隔符或新换行符的块中的所有数据,我觉得XSLT中的位置部分甚至没有被执行。
问题:我想测试每个父项的最后一个子项的位置,如果它是父项(currentRow)的最后一个子项(columnvalue),则包含一个新行,如果是&#,则包含一个分隔符39;不是。
我有一个XML,如下所示:
XML文件:
<?xml version='1.0'?>
<webRowSet xmlns='http://java.sun.com/xml/ns/jdbc'>
<data>
<currentRow>
<columnValue><![CDATA[]]></columnValue>
<columnValue><![CDATA[26068384]]></columnValue>
<columnValue><![CDATA[070-0010055-4842MAR18]]></columnValue>
<columnValue>2018-04-25</columnValue>
<columnValue>170.310</columnValue>
<columnValue><![CDATA[UI-004058]]></columnValue>
</currentRow>
<currentRow><columnValue><![CDATA[]]></columnValue>
<columnValue><![CDATA[26068385]]></columnValue>
<columnValue><![CDATA[070-0010058-5739MAR18]]></columnValue>
<columnValue>2018-04-25</columnValue>
<columnValue>209.900</columnValue>
<columnValue><![CDATA[UI-004057]]></columnValue>
</currentRow>
</data></webRowSet>
XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version ="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="Delimiter"><xsl:text>|</xsl:text></xsl:variable>
<xsl:variable name="NewLine"><xsl:text> </xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:text>EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo</xsl:text>
<xsl:text> </xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="webRowSet/data">
<xsl:for-each select="currentRow">
<xsl:for-each select="columnValue">
<xsl:value-of select="."/>
<xsl:variable name="Rec_position" select="count(../preceding-sibling::columnValue)+1"/>
<xsl:if test="$Rec_position=6"><xsl:value-of select="$NewLine"/></xsl:if>
<xsl:if test="$Rec_position!=6"><xsl:value-of select="$Delimiter"/></xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
TEXT中的输出应该是:
EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo
|26068384|070-0010055-4842MAR18|2018-04-25|170.310|UI-004058
|26068385|070-0010058-5739MAR18|2018-04-25|209.900|UI-004057
答案 0 :(得分:0)
XSLT中存在两个问题。
首先,您没有考虑到XML中的元素位于默认命名空间中这一事实,如根元素上的xmlns='http://java.sun.com/xml/ns/jdbc
所定义。
如果您确实只使用XSLT 1.0,则必须将该命名空间与XSLT中的前缀相关联,如此...
xmlns:j="http://java.sun.com/xml/ns/jdbc"
然后在select表达式中的所有元素之前使用该前缀。例如......
<xsl:template match="j:webRowSet/j:data">
其次,在你的count
考试中,..
表示父节点,当你真的想要计算当前节点的前一个兄弟节点时,你应该写这个......
<xsl:variable name="Rec_position" select="count(preceding-sibling::j:columnValue)+1"/>
虽然position()
函数在这里会做同样的事情。
<xsl:variable name="Rec_position" select="position()"/>
但是你真的想把列数硬编码为6吗?试试这个XSLT:
<xsl:stylesheet version ="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:j="http://java.sun.com/xml/ns/jdbc">
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="Delimiter"><xsl:text>|</xsl:text></xsl:variable>
<xsl:variable name="NewLine"><xsl:text> </xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:text>EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo</xsl:text>
<xsl:value-of select="$NewLine"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="j:webRowSet/j:data">
<xsl:for-each select="j:currentRow">
<xsl:for-each select="j:columnValue">
<xsl:if test="position() != 1"><xsl:value-of select="$Delimiter" /></xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
<xsl:value-of select="$NewLine"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
注意,如果你可以使用XSLT 2.0,你可以这样写:
<xsl:stylesheet version ="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://java.sun.com/xml/ns/jdbc">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="NewLine"><xsl:text> </xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:text>EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo</xsl:text>
<xsl:value-of select="$NewLine"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="webRowSet/data">
<xsl:for-each select="currentRow">
<xsl:value-of select="columnValue" separator="|"/>
<xsl:value-of select="$NewLine"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
请注意使用xpath-default-namespace
可以更轻松地处理默认命名空间。此外,在选择多个值时适用的separator
上使用xsl:value-of
。 (在XSLT 1.0中,xsl:value-of
只显示第一个值。)
答案 1 :(得分:0)
您忘了考虑名称空间。因此,将xmlns:j="http://java.sun.com/xml/ns/jdbc"
添加到XSLT文件的xsl:stylesheet
元素中。这样,您就可以使用正确的命名空间访问所有元素。
关于命名空间,将您的上一个模板更改为:
<xsl:template match="j:webRowSet/j:data">
<xsl:for-each select="j:currentRow">
<xsl:for-each select="j:columnValue">
<xsl:value-of select="."/>
<xsl:variable name="Rec_position" select="position()"/>
<xsl:if test="$Rec_position=6"><xsl:value-of select="$NewLine"/></xsl:if>
<xsl:if test="$Rec_position < 6"><xsl:value-of select="$Delimiter"/></xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
输出为:
EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo
|26068384|070-0010055-4842MAR18|2018-04-25|170.310|UI-004058
|26068385|070-0010058-5739MAR18|2018-04-25|209.900|UI-004057
这是一个非常简单的解决方案,只需要进行最少的修改。