我是XSLT的新手,我试图编写一些XSLT,它会使任何给定的XML变平,这样每当嵌套级别发生变化时就会出现一个新行。我的输入可以是任何XML文档,具有任意数量的嵌套级别,因此XSLT不知道该结构。由于我可以使用的工具,我的解决方案必须使用XSLT 1.0版。
例如。
<?xml version="1.0"?>
<ROWSET>
<ROW>
<CUSTOMER_ID>0</CUSTOMER_ID>
<NAME>Default Company</NAME>
<BONUSES>
<BONUSES_ROW>
<BONUS_ID>21</BONUS_ID>
<DESCRIPTION>Performance Bonus</DESCRIPTION>
</BONUSES_ROW>
<BONUSES_ROW>
<BONUS_ID>26</BONUS_ID>
<DESCRIPTION>Special Bonus</DESCRIPTION>
</BONUSES_ROW>
</BONUSES>
</ROW>
<ROW>
<CUSTOMER_ID>1</CUSTOMER_ID>
<NAME>Dealer 1</NAME>
<BONUSES>
<BONUSES_ROW>
<BONUS_ID>27</BONUS_ID>
<DESCRIPTION>June Bonus</DESCRIPTION>
<BONUS_VALUES>
<BONUS_VALUES_ROW>
<VALUE>10</VALUE>
<PERCENT>N</PERCENT>
</BONUS_VALUES_ROW>
<BONUS_VALUES_ROW>
<VALUE>11</VALUE>
<PERCENT>Y</PERCENT>
</BONUS_VALUES_ROW>
</BONUS_VALUES>
</BONUSES_ROW>
</BONUSES>
</ROW>
</ROWSET>
需要成为......
0, Default Company
21, Performance Bonus
26, Special Bonus
1, Dealer 1
27, June Bonus
10, N
11, Y
到目前为止我写的XSLT是......
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="iso-8859-1"/>
<xsl:strip-space elements="*" />
<xsl:template match="/*/child::*">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="*">
<xsl:value-of select="text()" />
<xsl:if test="position()!= last()"><xsl:text>,</xsl:text></xsl:if>
<xsl:if test="position()= last()"><xsl:text>
</xsl:text></xsl:if>
<xsl:apply-templates select="./child::*"/>
</xsl:template>
</xsl:stylesheet>
但我的输出不正确,有间隙和不必要的数据。
0,Default Company,
,21,Performance Bonus
26,Special Bonus
1,Dealer 1,
27,June Bonus,
,10,N
11,Y
似乎需要检查一个节点是否可以包含文本,但是我已经陷入困境并且可以使用XSLT专家的帮助。
答案 0 :(得分:2)
您可以通过执行以下操作来测试元素是否包含文本:*[text()]
示例...
XML输入
<ROWSET>
<ROW>
<CUSTOMER_ID>0</CUSTOMER_ID>
<NAME>Default Company</NAME>
<BONUSES>
<BONUSES_ROW>
<BONUS_ID>21</BONUS_ID>
<DESCRIPTION>Performance Bonus</DESCRIPTION>
</BONUSES_ROW>
<BONUSES_ROW>
<BONUS_ID>26</BONUS_ID>
<DESCRIPTION>Special Bonus</DESCRIPTION>
</BONUSES_ROW>
</BONUSES>
</ROW>
<ROW>
<CUSTOMER_ID>1</CUSTOMER_ID>
<NAME>Dealer 1</NAME>
<BONUSES>
<BONUSES_ROW>
<BONUS_ID>27</BONUS_ID>
<DESCRIPTION>June Bonus</DESCRIPTION>
<BONUS_VALUES>
<BONUS_VALUES_ROW>
<VALUE>10</VALUE>
<PERCENT>N</PERCENT>
</BONUS_VALUES_ROW>
<BONUS_VALUES_ROW>
<VALUE>11</VALUE>
<PERCENT>Y</PERCENT>
</BONUS_VALUES_ROW>
</BONUS_VALUES>
</BONUSES_ROW>
</BONUSES>
</ROW>
</ROWSET>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[text()]">
<xsl:if test="position() > 1">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:value-of select="."/>
<xsl:if test="not(following-sibling::*[text()])">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
文字输出
0, Default Company
21, Performance Bonus
26, Special Bonus
1, Dealer 1
27, June Bonus
10, N
11, Y
另外,请查看Built-in Template Rules,了解该样式表仅使用一个模板的原因。
修改强>
此样式表还将输出空元素的逗号:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[text() or not(*)]">
<xsl:if test="position() > 1">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:value-of select="."/>
<xsl:if test="not(following-sibling::*[text() or not(*)])">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
检查或验证您的XML。
In your XML, Start Node <ROWSET> does not end with </ROWSET>
If <ROWSET> node ends with </ROWSET> then, following XSL code will work for your expectation output
<xsl:template match="ROWSET">
<xsl:for-each select="ROW">
<xsl:value-of select="CUSTOMER_ID"/>, <xsl:value-of select="NAME"/><xsl:text> </xsl:text>
<xsl:for-each select="BONUSES/BONUSES_ROW">
<xsl:value-of select="BONUS_ID"/>, <xsl:value-of select="DESCRIPTION"/><xsl:text> </xsl:text>
<xsl:variable name="cnt" select="count(BONUS_VALUES/BONUS_VALUES_ROW)"/>
<xsl:if test="$cnt > 0">
<xsl:for-each select="BONUS_VALUES/BONUS_VALUES_ROW">
<xsl:value-of select="VALUE"/>, <xsl:value-of select="PERCENT"/><xsl:text> </xsl:text>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>