XSLT CallTemplate ForEach XML

2019-08-21 11:06发布

I need a little XSLT help. Couldn't figure out why the actual output is different from my expected output. Any help much appreciated!

XML

<?xml version="1.0"?>
<a>
  <b c="d"/>
  <b c="d"/>
  <b c="d"/>
</a>

XSL

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template name="foo">
        <xsl:param name="content"></xsl:param>
        <xsl:value-of select="$content"></xsl:value-of>
    </xsl:template>

    <xsl:template match="/">
        <xsl:call-template name="foo">
            <xsl:with-param name="content">
                <xsl:for-each select="a/b">
                    <e>
                        <xsl:value-of select="@c" />
                    </e>
                </xsl:for-each>
            </xsl:with-param>
        </xsl:call-template>
    </xsl:template>

Actual Output

<?xml version="1.0"?>
ddd

Desired Output

<?xml version="1.0"?>
<e>d</e>
<e>d</e>
<e>d</e>

Note: Calling the template is mandatory. In my situation the template does more with extension functions.

2条回答
做自己的国王
2楼-- · 2019-08-21 11:44

Contrary to what ABach says, your xsl:param is fine. The only thing you need to change is your xsl:value-of. It should be a xsl:copy-of:

<xsl:template name="foo">
    <xsl:param name="content"/>
    <xsl:copy-of select="$content"/>
</xsl:template>
查看更多
等我变得足够好
3楼-- · 2019-08-21 11:49

You're very close; you've just mixed up relative positioning and correct parameter usage within templates. Here's a slightly revised answer.

When this XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:template name="foo">
    <xsl:param name="pContent" />
    <xsl:for-each select="$pContent">
      <e>
        <xsl:value-of select="@c" />
      </e>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="/*">
    <xsl:call-template name="foo">
      <xsl:with-param name="pContent" select="*" />
    </xsl:call-template>
  </xsl:template>

</xsl:stylesheet>

...is applied to the original XML:

<?xml version="1.0"?>
<a>
  <b c="d" />
  <b c="d" />
  <b c="d" />
</a>

...the desired result is produced:

<?xml version="1.0"?>
<e>d</e>
<e>d</e>
<e>d</e>

In particular, notice the correct usage of <xsl:param> to include nodes based on their relative position. In your case, you are telling the XSLT parser to output the text values of the parameter that you're passing, rather than altering the nodes' contents in the way you want.

查看更多
登录 后发表回答