2012-03-28 48 views
0

我已经创建了一个XSLT,它在以下输入中查找月份标签,并拆分字符串并为每个字符串创建新标签。然而,我遇到的问题是,它只查看第一个月的标签,并且任何子标签<set>标签会自动填充第一组的结果。带输出字符串操作的XSLT错误

因此,对于这个输入:

<?xml version="1.0" encoding="UTF8"?> 
<Response xmlns="http://www.castiron.com/response"> 
    <payload> 
     <sets> 
      <month>JUN,JUL</month> 
      <season>Season11</season> 
      <productId>1111111</productId> 
     </sets> 
     <sets> 
      <month>AUG,SEP</month> 
      <season>Season12</season> 
      <productId>2222222</productId> 
     </sets> 
    </payload> 
</Response> 

SHOULD产品:

<?xml version="1.0" encoding="utf-8"?> 
<Response xmlns="http://www.castiron.com/response"> 
    <payload xmlns:r="http://www.castiron.com/response"> 
     <sets> 
      <month>JUN</month> 
      <season>Season11</season> 
      <productId>1111111</productId> 
     </sets> 
     <sets> 
      <month>JUL</month> 
      <season>Season11</season> 
      <productId>1111111</productId> 
     </sets> 
     <sets> 
      <month>AUG</month> 
      <season>Season12</season> 
      <productId>2222222</productId> 
     </sets> 
     <sets> 
      <month>SEP</month> 
      <season>Season12</season> 
      <productId>2222222</productId> 
     </sets> 
    </payload> 
</Response> 

但是其实际回应是:

<?xml version="1.0" encoding="utf-8"?> 
<Response xmlns="http://www.castiron.com/response"> 
    <payload xmlns:r="http://www.castiron.com/response"> 
     <sets> 
      <month>JUN</month> 
      <season>Season11</season> 
      <productId>1111111</productId> 
     </sets> 
     <sets> 
      <month>JUN</month> 
      <season>Season12</season> 
      <productId>2222222</productId> 
     </sets> 
     <sets> 
      <month>JUL</month> 
      <season>Season11</season> 
      <productId>1111111</productId> 
     </sets> 
     <sets> 
      <month>JUL</month> 
      <season>Season12</season> 
      <productId>2222222</productId> 
     </sets> 
    </payload> 
</Response> 

目前XSLT是:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:r="http://www.castiron.com/response" exclude-result-prefixes="r"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="@* | node()"> 
     <xsl:param name="month"/> 

     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"> 
       <xsl:with-param name="month" select="$month"/> 
      </xsl:apply-templates> 
     </xsl:copy> 

    </xsl:template> 

    <xsl:template match="r:month"> 
     <xsl:param name="month"/> 
     <month xmlns="http://www.castiron.com/response"> 
      <xsl:choose> 
       <xsl:when test="$month"> 
        <xsl:value-of select="$month"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:apply-templates/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </month> 
    </xsl:template> 

    <xsl:template name="splitMonths"> 
     <xsl:param name="months"/> 
     <xsl:variable name="firstMonth" select="substring-before($months,',')"/> 
     <xsl:variable name="month"> 
      <xsl:choose> 
       <xsl:when test="$firstMonth"> 
        <xsl:value-of select="$firstMonth"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$months"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 
     <xsl:variable name="otherMonths" select="substring-after($months,',')"/> 
     <xsl:if test="$month"> 
      <xsl:apply-templates> 
       <xsl:with-param name="month" select="$month"/> 
      </xsl:apply-templates> 
     </xsl:if> 
     <xsl:if test="$otherMonths"> 
      <xsl:call-template name="splitMonths"> 
       <xsl:with-param name="months" select="$otherMonths"/> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 

    <xsl:template match="r:payload"> 

     <payload xmlns="http://www.castiron.com/response"> 

      <xsl:call-template name="splitMonths"> 
       <xsl:with-param name="months" select="r:sets/r:month"/> 
      </xsl:call-template> 

     </payload> 
    </xsl:template> 

</xsl:stylesheet> 

任何人都可以帮忙,因为我一直在围绕这一天的大脑围绕着我!

UPDATE

我看通过每个<sets>标签循环的想法,因此使用在上面的填充这部分代码:

<xsl:template match="r:payload"> 
    <payload xmlns="http://www.castiron.com/response"> 
     <xsl:for-each select="r:sets"> 

     <xsl:call-template name="splitMonths"> 
      <xsl:with-param name="months" select="r:sets/r:month"/> 
     </xsl:call-template> 

     </xsl:for-each> 
    </payload> 
</xsl:template> 

但是它产生以下输出:

<?xml version="1.0" encoding="utf-8"?> 
<Response xmlns="http://www.castiron.com/response"> 
    <payload xmlns:r="http://www.castiron.com/response"> 
     <month/> 
     <season>SS11</season> 
     <productId>3600596</productId> 
     <month/> 
     <season>AW12</season> 
     <productId>7001258</productId> 
    </payload> 
</Response> 

回答

2

这里是一个纯XSLT 1.0溶液不需要任何扩展名:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns="http://www.castiron.com/response" 
    xmlns:r="http://www.castiron.com/response" 
    exclude-result-prefixes="r"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="r:sets"> 
    <xsl:apply-templates select="r:month"/> 
    </xsl:template> 

    <xsl:template match="r:month"> 
    <xsl:param name="text" select="."/> 
    <xsl:choose> 
     <xsl:when test="not(contains($text, ','))"> 
     <sets> 
      <month> 
      <xsl:value-of select="$text"/> 
      </month> 
      <xsl:apply-templates select="../*[not(self::r:month)]"/> 
     </sets> 
     </xsl:when> 
     <xsl:otherwise> 
     <sets> 
      <month> 
      <xsl:value-of select="substring-before($text, ',')"/> 
      </month> 
      <xsl:apply-templates select="../*[not(self::r:month)]"/> 
     </sets> 
     <xsl:apply-templates select="."> 
      <xsl:with-param name="text" select="substring-after($text, ',')"/> 
     </xsl:apply-templates> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

随着XSLT 2.0是,更容易:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns="http://www.castiron.com/response" 
    xmlns:r="http://www.castiron.com/response" 
    exclude-result-prefixes="r"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="r:sets"> 
    <xsl:apply-templates select="r:month"/> 
    </xsl:template> 

    <xsl:template match="r:month"> 
    <xsl:param name="names" select="tokenize(., ',')"/> 
    <xsl:choose> 
     <xsl:when test="not($names[2])"> 
     <sets> 
      <month> 
      <xsl:value-of select="$names[1]"/> 
      </month> 
      <xsl:apply-templates select="../*[not(self::r:month)]"/> 
     </sets> 
     </xsl:when> 
     <xsl:otherwise> 
     <sets> 
      <month> 
      <xsl:value-of select="$names[1]"/> 
      </month> 
      <xsl:apply-templates select="../*[not(self::r:month)]"/> 
     </sets> 
     <xsl:apply-templates select="."> 
      <xsl:with-param name="names" select="$names[position() gt 1]"/> 
     </xsl:apply-templates> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

[编辑] XSLT 2.0溶液是在先前的XSLT 1.0解决方案之后建模的,但我认为以下方法更加紧凑,更易于理解和执行:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns="http://www.castiron.com/response" 
    xmlns:r="http://www.castiron.com/response" 
    exclude-result-prefixes="r"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="r:sets"> 
    <xsl:variable name="this-set" select="."/> 
    <xsl:for-each select="tokenize(r:month, ',')"> 
     <sets> 
     <month> 
      <xsl:value-of select="."/> 
     </month> 
     <xsl:apply-templates select="$this-set/*[not(self::r:month)]"/> 
     </sets> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 
1

如何使用分词器和显式匹配,如下所示:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:r="http://www.castiron.com/response" 
    xmlns:s="http://exslt.org/strings" 
    exclude-result-prefixes="r"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="*|r:*"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="r:sets"> 
    <xsl:variable name="months" select="s:tokenize(r:month, ',')"/> 
    <xsl:variable name="this" select="*[name() != 'month']"/> 
    <xsl:for-each select="$months"> 
     <xsl:element name="sets" namespace="http://www.castiron.com/response"> 
     <xsl:element name="month" namespace="http://www.castiron.com/response"> 
      <xsl:value-of select="."/> 
     </xsl:element> 
     <!-- all the other children --> 
     <xsl:copy-of select="$this"/> 
     </xsl:element> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 
+0

当我在氧气中运行时,出现以下错误'URL http://exslt.org/strings没有标识外部Java类',然后突出显示此行'' – MMKD 2012-03-28 11:10:46

+0

我不知道氧气是什么,但它是一个xslt扩展名,并且有源代码,请参阅http:// www。 exslt.org/str/index.html – hroptatyr 2012-03-28 11:13:03

+0

也许它适用于'extension-element-prefixes =“s”',因为他们提示 – hroptatyr 2012-03-28 11:13:40