这就是我所拥有的。
我的数据: data.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="myxslt2.xslt"?>
<data>
<foo>
<innerfoo1>inner-foo-1-text</innerfoo1>
<innerfoo2>inner-foo-2-text</innerfoo2>
</foo>
<bar>Hello World</bar>
<foobar>This is a test</foobar>
</data>
我的元数据 - 这是告诉xslt要显示哪些数据节点。
metadata.xml中
<Metadata>
<Data>
<Detail>foobar</Detail>
<Detail>bar</Detail>
<Detail>foo/innerfoo1</Detail>
</Data>
</Metadata>
我们希望显示除innerfoo2之外的所有内容。
我的xslt: 的 myxslt.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" version="1.0">
<xsl:output method="html" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" indent="yes"/>
<xsl:variable name="main" select="/data"/>
<xsl:template name="myTemplate">
<xsl:param name="myparam"/>
<xsl:param name="node"/>
Node: <xsl:value-of select="$node"/><br/>
Inner:<xsl:value-of select="msxsl:node-set($myparam)/data/*[local-name() = $node][1]"/>
</xsl:template>
<xsl:template match="/data">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
HTML STARTS
<br/>
<xsl:variable name="data" select="."/>
Outer1:<xsl:value-of select="$data"/>
<br/>
Outer2:<xsl:value-of select="$data/foobar"/>
<br/>
<xsl:variable name="defaultMetadata" select="document('metadata.xml')"/>
<xsl:for-each select="msxsl:node-set($defaultMetadata)/Metadata/Data/Detail">
<br/>----<br/>
<xsl:call-template name="myTemplate">
<xsl:with-param name="node">
<xsl:value-of select="."></xsl:value-of>
</xsl:with-param>
<xsl:with-param name="myparam">
<xsl:copy-of select="$data"/>
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</html>
</xsl:template>
</xsl:stylesheet>
(用于提高可读性的pastebin - http://pastebin.com/Uw7bFYWM)
输出:
HTML STARTS
Outer1: inner-foo-1-text inner-foo-2-text Hello World This is a test
Outer2:This is a test
----
Node: foobar
Inner:This is a test
----
Node: bar
Inner:Hello World
----
Node: foo/innerfoo1
Inner:
所以我正在做的是循环遍历元数据的每个细节元素,并调用传递数据的模板,即要显示的节点的名称。
模板然后解析该节点并显示它。
所以你可以在这里看到它可以很好地解析单级元素,但是当它不止一个元素时,我不能使用local-name() = $node
比较。
我想做的是:
Inner:<xsl:value-of select="msxsl:node-set($myparam)/data/$node"/>
但这不起作用。
怎么能实现这个目标?
答案 0 :(得分:1)
根据问题评论中的建议,这是我的动态评估简单表达式的递归函数。
<xsl:template name="recursiveTemplate">
<xsl:param name="data"/>
<xsl:param name="node"/>
<xsl:for-each select="msxsl:node-set($data)/*/*">
<xsl:choose>
<xsl:when test="contains($node,'/')">
<!--not the final node so recursion required-->
<xsl:if test="substring-before($node, '/') = local-name() ">
<xsl:call-template name="recursiveTemplate">
<xsl:with-param name="data">
<xsl:copy-of select="."/>
</xsl:with-param>
<xsl:with-param name="node">
<xsl:value-of select="substring-after($node,'/')"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<!--final node, so find the one that matches -->
<xsl:if test="local-name()= $node">
<xsl:value-of select="."/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
用
调用 <xsl:call-template name="recursiveTemplate">
<xsl:with-param name="data">
<xsl:copy-of select="msxsl:node-set($myparam)/data"/>
</xsl:with-param>
<xsl:with-param name="node">
<xsl:value-of select="$node"/>
</xsl:with-param>
</xsl:call-template>
这似乎令人难以置信的冗长和复杂,但它的确有效。 关于如何以其他方式实施的任何建议?
答案 1 :(得分:1)
如果您遇到XSLT 1.0并且无法使用任何使用动态评估的扩展函数,那么通过某些修复,可以在纯XSLT中执行此操作。这个特定答案的限制是 metadata.xml 中的xpath表达式不是没有任何条件的节点列表。
在我展示这个特定的答案之前,值得注意的是你不需要在这里使用节点集扩展函数,即使在你当前的XSLT中也是如此。如果要将“结果树片段”转换为可由XSLT匹配的节点,则可以使用node-set。如果直接引用输入文档,则实际上并不需要它。您认为自己需要它的原因实际上是因为这条线......
<xsl:with-param name="myparam">
<xsl:copy-of select="$data"/>
</xsl:with-param>
你应该这样做..
<xsl:with-param name="myparam" select="$data"/>
使用 xsl:copy-of 表示您实际上是在创建一个结果树片段,但后一个调用不是创建任何副本,而是引用原始节点。
无论如何,要解决此问题,可以将 myTemplate 制作为递归模板。您的想法是检查当前参数是否包含斜杠。如果是这样,您会在斜杠之前找到具有该元素名称的节点,并递归调用 myTemplate 作为新参数,并在斜杠后传递剩余的expressin。
<xsl:template name="myTemplate">
<xsl:param name="myparam"/>
<xsl:param name="node"/>
<xsl:choose>
<xsl:when test="contains($node, '/')">
<xsl:call-template name="myTemplate">
<xsl:with-param name="node" select="substring-after($node, '/')" />
<xsl:with-param name="myparam" select="$myparam/*[local-name() = substring-before($node, '/')][1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
Node: <xsl:value-of select="$node"/><br/>
Inner:<xsl:value-of select="$myparam/*[local-name() = $node][1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
因此只有在得到没有斜杠的表达式时才会生成输出。
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
indent="yes"/>
<xsl:variable name="main" select="/data"/>
<xsl:template name="myTemplate">
<xsl:param name="myparam"/>
<xsl:param name="node"/>
<xsl:choose>
<xsl:when test="contains($node, '/')">
<xsl:call-template name="myTemplate">
<xsl:with-param name="node" select="substring-after($node, '/')" />
<xsl:with-param name="myparam" select="$myparam/*[local-name() = substring-before($node, '/')][1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
Node: <xsl:value-of select="$node"/><br/>
Inner:<xsl:value-of select="$myparam/*[local-name() = $node][1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/data">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
HTML STARTS
<br/>
<xsl:variable name="data" select="."/>
Outer1:<xsl:value-of select="$data"/>
<br/>
Outer2:<xsl:value-of select="$data/foobar"/>
<br/>
<xsl:variable name="defaultMetadata" select="document('metadata.xml')"/>
<xsl:for-each select="$defaultMetadata/Metadata/Data/Detail">
<br/>----<br/>
<xsl:call-template name="myTemplate">
<xsl:with-param name="node" select="." />
<xsl:with-param name="myparam" select="$data"/>
</xsl:call-template>
</xsl:for-each>
</html>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:-1)
只需更换
即可<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" version="1.0">
带
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext msxsl" version="1.0">
和msxsl:node-set
与ext:node-set
一起使用。
完成xslt如下:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext msxsl" version="1.0">
<xsl:output method="html" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" indent="yes"/>
<xsl:variable name="main" select="/data"/>
<xsl:template name="myTemplate">
<xsl:param name="myparam"/>
<xsl:param name="node"/> Node: <xsl:value-of select="$node"/><br/> Inner:<xsl:choose>
<xsl:when test="contains($node,'foo/')"><xsl:value-of
select="ext:node-set($myparam)/data/foo/*[local-name() = substring-after($node,'/')][1]"
/></xsl:when>
<xsl:otherwise><xsl:value-of select="ext:node-set($myparam)/data/*[local-name() = $node][1]"
/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/data">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> HTML STARTS <br/>
<xsl:variable name="data" select="."/> Outer1:<xsl:value-of select="$data"/>
<br/> Outer2:<xsl:value-of select="$data/foobar"/>
<br/>
<xsl:variable name="defaultMetadata"
select="document('metadata.xml')"/>
<xsl:for-each select="ext:node-set($defaultMetadata)/Metadata/Data/Detail">
<br/>----<br/>
<xsl:call-template name="myTemplate">
<xsl:with-param name="node"><xsl:value-of select="."/></xsl:with-param>
<xsl:with-param name="myparam"><xsl:copy-of select="$data"/></xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</html>
</xsl:template>
</xsl:stylesheet>