是否可以从XSLT中删除xml属性并使用生成的转换?
换句话说,我有以下XML:
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="XML_TEST.xslt"?>
<report xmlns="abc123">
<book>
<page id="22">
</page>
<page id="23">
</page>
</book>
</report>
我知道我可以使用以下XSLT去除属性:
<xsl:template match ="@*" >
<xsl:attribute name ="{local-name()}" >
<xsl:value-of select ="." />
</xsl:attribute>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match ="*" >
<xsl:element name ="{local-name()}" >
<xsl:apply-templates select ="@* | node()" />
</xsl:element>
</xsl:template>
但如果我想阅读这些值,请使用以下模板
<xsl:template match="report">
<xsl:for-each select="book/page">
<xsl:value-of select="@id"/>
</xsl:for-each>
</xsl:template>
我可以将该模板链接到前两个的输出吗?
提前致谢,
-R
答案 0 :(得分:1)
是否可以删除xml 来自XSLT的属性和使用 结果变换?
是的,只需搜索“多次转化”,您就可以找到很多具有良好代码示例的答案。
但是,对于您想要做的事情,此类转换链接过于复杂且完全没必要。
只需使用:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="abc123" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="x:page">
<xsl:value-of select="@id"/>
</xsl:template>
</xsl:stylesheet>
如果事先不知道XML文档的默认命名空间,您仍然可以一次性生成想要的结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="*[name()='page']">
<xsl:value-of select="@id"/>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
这个问题有些奇怪:我看不出你的问题标题与内容的匹配程度。
在标题中,您要求进行两次传递转换,其中第一次传递必须删除属性,第二次传递必须对其进行处理。
在内容中,您会显示两个输出节点和属性的本地名称的模板,之后,您会在另一个模板中显示您希望使用属性获取其值。 .. :))
根据@Dimitre的回答回复了你问题的内容(我认为这并没有解决真正的问题)我会尝试回答你问题的标题 ,这看起来更有趣(并且可以回答)。
从XSLT中移除属性 ...
要删除属性(并获取没有名称空间的转换),您可以使用Identity Transformation。因为您需要多次传递,所以必须在第一次传递中复制变量的内容。
您可以使用modes来解决第一遍中元素的过程。
...并使用结果集
要使用结果集(正式名称为result tree fragment),您需要使用引用第一遍中定义的变量来应用模板。欢迎!这是第二遍:)
由于XSLT 2.0能够将模板应用于RTF,因此XSLT 2.0中的两次传递转换比XSLT 1.0更易于访问。在XSLT 1.0中,您将需要一个名为node-set()
的特定扩展函数。
XSLT 2.0看起来像这样(纯粹的例子):
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="abc123"
version="2.0">
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:variable name="FirstPass">
<xsl:copy>
<xsl:apply-templates select="/" mode="FirstPass"/>
</xsl:copy>
</xsl:variable>
<xsl:apply-templates select="$FirstPass/report/book/page"/>
</xsl:template>
<xsl:template match="node()" mode="FirstPass">
<xsl:element name="{local-name()}">
<xsl:apply-templates select ="node()" mode="FirstPass"/>
</xsl:element>
</xsl:template>
<xsl:template match="page">
<xsl:value-of select="count(@*)"/>
</xsl:template>
</xsl:stylesheet>
结果(应用于您的输入示例)
00
XSLT 1.0 看起来非常相似,但转换根元素:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="abc123"
xmlns:exslt="http://exslt.org/common"
version="2.0">
和第二次传递:
<xsl:apply-templates select="exslt:node-set($FirstPass)/report/book/page"/>
答案 2 :(得分:0)
许多转换最好分成一个管道,管道的每个阶段都执行一个简单的任务。
您可以在单个样式表中进行多阶段转换(通过将结果保存在变量中,尤其是使用XSLT 2.0),或者您可以使用多个样式表来执行此操作。您可以使用各种技术(XProc,Coccoon,Orbeon,Ant,xmlsh)或您自己的Java / C#代码控制涉及多个样式表的管道。使用多个样式表的优点是管道的组件具有高度可重用性。