[英]XSL to transform only elements in a certain namespace
我有一个XML文件,其结构如下:-
<catalog xmlns="format_old" xmlns:final="format_new">
<final:book>
<final:title>blah</final:title>
<final:author>more blah</final:author>
</final:book>
<book>
<description title="blah2"/>
<writer name="more blah2"/>
</book>
</catalog>
显然,这是问题的简化版本。 我想要做的就是将其转换为类似:-
<catalog xmlns="format_new">
<book>
<title>blah</title>
<author>more blah</author>
</book>
<book>
<title>blah2</title>
<author>more blah2</author>
</book>
</catalog>
我现在拥有的样式表是这样的:-
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:orig="format_old"
xmlns="format_new"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="//orig:book">
<xsl:element name="title">
<xsl:value-of select="./orig:description/@title" />
</xsl:element>
<xsl:element name="author">
<xsl:value-of select="./orig:writer/@name" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
这给了我这样的输出:-
<catalog xmlns="format_old">
<book xmlns="format_new">
<title>blah</title>
<author>more blah</author>
</book>
<book xmlns:orig="format_old" xmlns="format_new">
<title>blah2</title>
</author>more blah2</author>
</book>
</catalog>
此样式表有两个问题:
1。)(主要问题)复制根元素,而不是更改根元素的默认名称空间。 因此,目录元素基本上仍将位于命名空间format_old中。
2.)(次要问题)这会将元素转换为:-
<book xmlns:orig="format_old" xmlns="format_new">
...
</book>
而不是从根元素中选择名称空间,以使其保持不变
<book>
...
</book>
我在这里想念什么? 我正在使用Xalan-C。
我认为以下应该做:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns="format_new"
xmlns:ns1="format_old"
exclude-result-prefixes="ns1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@* | text() | comment() | processing-instruction()">
<xsl:copy/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="ns1:book/ns1:description[@title]">
<title>
<xsl:value-of select="@title"/>
</title>
</xsl:template>
<xsl:template match="ns1:book/ns1:writer[@name]">
<author>
<xsl:value-of select="@name"/>
</author>
</xsl:template>
</xsl:stylesheet>
Saxon 6.5.5将您的输入转换为
<?xml version="1.0" encoding="utf-8"?><catalog xmlns="format_new">
<book>
<title>blah</title>
<author>more blah</author>
</book>
<book>
<title>blah2</title>
<author>more blah2</author>
</book>
</catalog>
你近了 您的默认模板会收集您没有其他模板的所有内容。
您的第一个问题是,他们要使用orig:catalog元素并将其原样写入,这不是您想要的。 简单修复:为其添加模板。
第二个问题是管理输出中的名称空间声明。 在这里,几种技术可能会有所帮助:
请仔细阅读规范或您最喜欢的XSLT参考中的xsl:exclude-result-prefixes文档。 使用它来告诉您的处理器,您不需要周围的旧名称空间都具有名称空间声明。
如果要利用以下事实,请使用xsl:element构造函数而不是文字结果元素:来自文字结果元素的输出始终带有样式表中LRE上所有inscope命名空间前缀的事实。 有关更多详细信息,请参见此SO问题 。
在SAX或您喜欢的编辑器中编写一个简单的过滤器,以完全控制声明名称空间的位置以及方式。 (XSLT的设计认为,您应该非常担心名称空间声明,结果很难很好地控制它们。)
训练自己不要在输出中有多余的名称空间声明时过分关心,并且只要所有内容都正确绑定,就可以让下游使用者编写正确的操作,这样它们就不会受到无关的名称空间声明的困扰。
不同的人使用这些不同的技术可获得不同的成功水平。 我自己,我发现最后一个特别有效,并且我只担心当其他问题对我不利时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.