我有以下xml,其中包含产品信息。每个产品的描述有时会出现在下一个产品之前的nexts行中,因为在一定数量的字符之后,描述会被拆分。
<?xml version="1.0" encoding="utf-8"?>
<root>
<row>
<rowWords>5.00</rowWords>
<rowWords>PRODUCTCODE1</rowWords>
<rowWords>DESCRIPTIONWORD1</rowWords>
<rowWords>DESCRIPTIONWORD2</rowWords>
<rowWords>DESCRIPTIONWORD3</rowWords>
<rowWords>DESCRIPTIONWORD4</rowWords>
<rowWords>DESCRIPTIONWORD5</rowWords>
<rowWords>11.28</rowWords>
<rowWords>56.40</rowWords>
</row>
<row>
<rowWords>DESCRIPTIONWORD6</rowWords>
</row>
<row>
<rowWords>6.00</rowWords>
<rowWords>PRODUCTCODE2</rowWords>
<rowWords>DESCRIPTIONWORD1</rowWords>
<rowWords>DESCRIPTIONWORD2</rowWords>
<rowWords>DESCRIPTIONWORD3</rowWords>
<rowWords>DESCRIPTIONWORD4</rowWords>
<rowWords>DESCRIPTIONWORD5</rowWords>
<rowWords>11.00</rowWords>
<rowWords>66.00</rowWords>
</row>
<row>
<rowWords>DESCRIPTIONWORD6</rowWords>
<rowWords>DESCRIPTIONWORD7</rowWords>
<rowWords>DESCRIPTIONWORD8</rowWords>
</row>
<row>
<rowWords>DESCRIPTIONWORD9</rowWords>
<rowWords>DESCRIPTIONWORD10</rowWords>
</row>
<row>
<rowWords>10.00</rowWords>
<rowWords>PRODUCTCODE3</rowWords>
<rowWords>DESCRIPTIONWORD1</rowWords>
<rowWords>DESCRIPTIONWORD2</rowWords>
<rowWords>10.00</rowWords>
<rowWords>100.00</rowWords>
</row>
.
. any amount of rows containing products
.
</root>
描述以及产品数量的变化,所以我不知道如何将产品描述整合在一起。
这是我已经完成的xsl。
<?xml version='1.0'?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="something">
<xsl:output indent="yes"/>
<xsl:template match="/root">
<a:Invoice>
<Products>
<xsl:for-each select="row[position()>=5 and position()<=last()-5]">
<!-- With this if, i prevent create a product node with partial description-->
<xsl:if test="number(rowWords[1])">
<Product>
<xsl:attribute name="quantity"><xsl:value-of select="rowWords[1]"/></xsl:attribute>
<xsl:attribute name="productCode"><xsl:value-of select="rowWords[2]"/></xsl:attribute>
<!--Here is the problem (Thank you Dimitri) -->
<xsl:attribute name="description">
<xsl:call-template name="constructDescription">
<xsl:with-param name="pRow" select="."/>
<xsl:with-param name="pPosition" select="position()"/>
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="unitValue"><xsl:value-of select="rowWords[last()-1]"/></xsl:attribute>
<xsl:attribute name="amount"><xsl:value-of select="rowWords[last()]"/></xsl:attribute>
</Product>
</xsl:if>
</xsl:for-each>
</Products>
</a:Invoice>
</xsl:template>
<xsl:template name="constructDescription">
<xsl:param name="pRow"/>
<xsl:param name="pPosition"/>
<xsl:for-each select="$pRow/*[position() >= 3 and position() <= last() -2]">
<xsl:value-of select="concat(.,' ')"/>
</xsl:for-each>
<xsl:if test="$pRow/following-sibling::*[not(number(*[1])=number(*[1]))]">
<xsl:call-template name="constructDescription">
<xsl:with-param name="pRow" select="$pRow/following-sibling::
*[position()=number($pPosition)+1]"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
这是输出
<?xml version='1.0' ?>
<a:Invoice>
<Products>
<Product quantity="5.00" productCode="PRODUCTCODE1" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 " unitValue="11.28" amount="56.40"/>
<Product quantity="6.00" productCode="PRODUCTCODE2" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 " unitValue="11.00" amount="66.00"/>
<Product quantity="10.00" productCode="PRODUCTCODE3" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 " unitValue="10.00" amount="100.00"/>
</Products>
</a:Invoice>
发生了什么事?问题是当我再次调用constructDescription时!但我不知道如何解决它!
非常感谢!
答案 0 :(得分:2)
此转换使用命名模板,当使用包含产品的row
参数调用时,会生成一个包含完整描述的字符串:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowingDesc"
match="row[not(number(*[1])=number(*[1]))]"
use="generate-id(preceding-sibling::row[number(*[1])=number(*[1])][1])"/>
<xsl:template match="/">
<xsl:call-template name="constructDescription">
<xsl:with-param name="pRow" select="/*/*[1]"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="constructDescription">
<xsl:param name="pRow"/>
<xsl:for-each select=
"$pRow/*[position() >= 3
and
not(position() > count($pRow/*) -2)
]
">
<xsl:value-of select="concat(.,' ')"/>
</xsl:for-each>
<xsl:for-each select="key('kFollowingDesc', generate-id($pRow))">
<xsl:value-of select="concat(.,' ')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
将此转换应用于以下XML文档(您的,但结构良好且显着截断):
<root>
<row>
<rowWords>6.00</rowWords>
<rowWords>PRODUCTCODE2</rowWords>
<rowWords>DESCRIPTIONWORD1</rowWords>
<rowWords>DESCRIPTIONWORD2</rowWords>
<rowWords>DESCRIPTIONWORD3</rowWords>
<rowWords>DESCRIPTIONWORD4</rowWords>
<rowWords>DESCRIPTIONWORD5</rowWords>
<rowWords>DESCRIPTIONWORD6</rowWords>
<rowWords>DESCRIPTIONWORD7</rowWords>
<rowWords>DESCRIPTIONWORD8</rowWords>
<rowWords>DESCRIPTIONWORD9</rowWords>
<rowWords>11.00</rowWords>
<rowWords>66.00</rowWords>
</row>
<row>
<rowWords>DESCRIPTIONWORD10</rowWords>
<rowWords>DESCRIPTIONWORD11</rowWords>
<rowWords>DESCRIPTIONWORD12</rowWords>
<rowWords>DESCRIPTIONWORD13</rowWords>
</row>
</root>
生成了正确的描述:
DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 DESCRIPTIONWORD10 DESCRIPTIONWORD11 DESCRIPTIONWORD12 DESCRIPTIONWORD13
解释:此命名模板应该是不言自明的,除了测试一些项目是否为数字,即:
number($x) = number($x)
当true()
是一个数字(或者可以成功地转换为数字的任何类型的值)时,这会准确评估为$x
。
我们正在测试:
not(number(*[1])=number(*[1]))
仅当下一行的第一个true()
子项不是数字时评估为rowWords
- 这意味着它包含更多描述字。
最后:所有这一切,都集成到了OP的代码中:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="something">
<xsl:output indent="yes"/>
<xsl:key name="kFollowingDesc"
match="row[not(number(*[1])=number(*[1]))]"
use="generate-id(preceding-sibling::row[number(*[1])=number(*[1])][1])"/>
<xsl:template match="/root">
<a:Invoice>
<Products>
<xsl:for-each select="row[number(*[1])=number(*[1])]">
<!-- With this if, i prevent create a product node with partial description-->
<xsl:if test="number(rowWords[1])">
<Product>
<xsl:attribute name="quantity">
<xsl:value-of select="rowWords[1]"/>
</xsl:attribute>
<xsl:attribute name="productCode">
<xsl:value-of select="rowWords[2]"/>
</xsl:attribute>
<!--Here is the problem (Thank you Dimitri) -->
<xsl:variable name="vDescriptions">
<xsl:call-template name="constructDescription">
<xsl:with-param name="pRow" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:attribute name="description">
<xsl:value-of select="normalize-space($vDescriptions)"/>
</xsl:attribute>
<xsl:attribute name="unitValue">
<xsl:value-of select="rowWords[last()-1]"/>
</xsl:attribute>
<xsl:attribute name="amount">
<xsl:value-of select="rowWords[last()]"/>
</xsl:attribute>
</Product>
</xsl:if>
</xsl:for-each>
</Products>
</a:Invoice>
</xsl:template>
<xsl:template name="constructDescription">
<xsl:param name="pRow"/>
<xsl:for-each select=
"$pRow/*[position() >= 3
and
not(position() > count($pRow/*) -2)
]
">
<xsl:value-of select="concat(.,' ')"/>
</xsl:for-each>
<xsl:for-each select="key('kFollowingDesc', generate-id($pRow))">
<xsl:value-of select="concat(.,' ')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
将此转换应用于他提供的新XML文档:
<root>
<row>
<rowWords>5.00</rowWords>
<rowWords>PRODUCTCODE1</rowWords>
<rowWords>DESCRIPTIONWORD1</rowWords>
<rowWords>DESCRIPTIONWORD2</rowWords>
<rowWords>DESCRIPTIONWORD3</rowWords>
<rowWords>DESCRIPTIONWORD4</rowWords>
<rowWords>DESCRIPTIONWORD5</rowWords>
<rowWords>11.28</rowWords>
<rowWords>56.40</rowWords>
</row>
<row>
<rowWords>DESCRIPTIONWORD6</rowWords>
</row>
<row>
<rowWords>6.00</rowWords>
<rowWords>PRODUCTCODE2</rowWords>
<rowWords>DESCRIPTIONWORD1</rowWords>
<rowWords>DESCRIPTIONWORD2</rowWords>
<rowWords>DESCRIPTIONWORD3</rowWords>
<rowWords>DESCRIPTIONWORD4</rowWords>
<rowWords>DESCRIPTIONWORD5</rowWords>
<rowWords>11.00</rowWords>
<rowWords>66.00</rowWords>
</row>
<row>
<rowWords>DESCRIPTIONWORD6</rowWords>
<rowWords>DESCRIPTIONWORD7</rowWords>
<rowWords>DESCRIPTIONWORD8</rowWords>
</row>
<row>
<rowWords>DESCRIPTIONWORD9</rowWords>
<rowWords>DESCRIPTIONWORD10</rowWords>
</row>
<row>
<rowWords>10.00</rowWords>
<rowWords>PRODUCTCODE3</rowWords>
<rowWords>DESCRIPTIONWORD1</rowWords>
<rowWords>DESCRIPTIONWORD2</rowWords>
<rowWords>10.00</rowWords>
<rowWords>100.00</rowWords>
</row> . . any amount of rows containing products .
</root>
产生了想要的正确结果:
<a:Invoice xmlns:a="something">
<Products>
<Product quantity="5.00" productCode="PRODUCTCODE1" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6" unitValue="11.28" amount="56.40" />
<Product quantity="6.00" productCode="PRODUCTCODE2" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 DESCRIPTIONWORD10" unitValue="11.00" amount="66.00" />
<Product quantity="10.00" productCode="PRODUCTCODE3" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2" unitValue="10.00" amount="100.00" />
</Products>
</a:Invoice>