我想在由XML文件中的数据确定的XSL中动态创建XPath表达式。 (即XML数据被“连接”以创建XPath表达式)。
XML数据示例:
<criteria>
<criterion>AAA</criterion>
<criterion>BBB</criterion>
<criterion>CCC</criterion>
</criteria>
我希望XPath表达式如何显示的示例:
//AAA | //BBB | //CCC
这个动态生成需要在XSL文件中完成。
我对XSL(和家人)相当陌生,并希望了解如何解决这个问题。
谢谢!
编辑: 提供更多背景.... 我需要做的是生成一个XPath,用于创建一个第二个 XSL,它转换完全不同的XML文件。我知道如何从XSL创建XSL,我只需要动态创建XPath表达式。如果我可以修改变量(我从其他地方读取,我不能),我只是将节点连接在一起形成一个表达式。然后从那里我将使用变量名称,无论我需要它。不幸的是我不能这样做.. :(
答案 0 :(得分:3)
以下将创建示例XPATH字符串作为针对示例XML文件运行时“generatedXPATH”变量的值:
<xsl:variable name="generatedXPATH">
<xsl:for-each select="/criteria/criterion">
<xsl:text>//</xsl:text>
<xsl:value-of select="." />
<xsl:if test="position()!=last()">
<xsl:text> | </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
您可以在样式表中使用该变量来生成样式表,以构建模板@match
这样的值:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xslt="http://www.w3.org/1999/XSL/TransformAlias"
version="1.0">
<xsl:namespace-alias stylesheet-prefix="xslt" result-prefix="xsl"/>
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:variable name="generatedXPATH">
<xsl:for-each select="/criteria/criterion">
<xsl:text>//</xsl:text>
<xsl:value-of select="." />
<xsl:if test="position()!=last()">
<xsl:text> | </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xslt:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xslt:template>
<xsl:attribute name="match">
<xsl:value-of select="$generatedXPATH" />
</xsl:attribute>
<xsl:comment>Do something special, like select the value of the matched elements</xsl:comment>
<xslt:value-of select="." />
</xslt:template>
</xslt:stylesheet>
</xsl:template>
</xsl:stylesheet>
针对示例运行时,XML会生成此样式表:
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//AAA | //BBB | //CCC">
<!--Do something special, like select the value of the matched elements-->
<xsl:value-of select="." />
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:2)
可以在XSLT中动态创建XPath表达式,但不能对这些表达式进行动态评估(至少在XSLT 2.1之前)。
您可以在XSLT中以其他方式完成所需的操作。
以下是一个例子:
这种转变:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<my:criteria>
<criterion>a</criterion>
<criterion>b</criterion>
<criterion>c</criterion>
</my:criteria>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()=document('')/*/my:criteria/*]">
<xsl:element name="{name()}-{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
应用于此XML文档时:
<t>
<a>
<x/>
<y/>
<b>
<c/>
<d/>
</b>
</a>
</t>
<强>产生强>:
<t>
<a-a>
<x></x>
<y></y>
<b-b>
<c-c></c-c>
<d></d>
</b-b>
</a-a>
</t>
也就是说,我们只以特殊方式处理任何元素(文档中的任何位置),其名称为a
或b
或c
。
答案 2 :(得分:0)
您无法使用xsl或xpath动态执行此操作。你将不得不使用PHP或其他(取决于你在哪里使用它)。如果您有一组有限的节点,则可以使用// AAA | // BBB | // CCC它会起作用,但如果你想让它在许多不同的节点上工作,那么它并没有用。
有关XPath的更多信息,请参阅here。
编辑: Jeez,你编辑过它。
使用/ criteria / [criterion = AAA]。
再次编辑:
查询应为:“/criteria/[criterion=AAA] | criteria/[criterion=BBB] | criteria/[criterion=CCC]
”。虽然我忘了怎么做,你可能会改写这个更有效率。请参阅this tutorial,了解它是如何完成的。希望有所帮助。