我正在努力将 xml 文件从旧版本转换为新版本。这是我正在使用的基本模板:
<xsl:template match="*">
<xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
<xsl:copy-of select="@*"></xsl:copy-of>
<xsl:apply-templates></xsl:apply-templates>
</xsl:element>
</xsl:template>
但是,新版本的 xml 模式要求所有具有文本值的元素都不能为空字符串。如此古老的 xml 文档如:
<dataset>
<title> </title>
</dataset>
在新版本中将失效。我试图修改文本节点的默认模板。新的文本模板将检查文本节点,如果文本代码为空字符串,它将终止转换,否则会将值复制到输出 xml。这是模板:
<xsl:template match="text()">
<xsl:variable name="text-value" select="."/>
<xsl:if test="normalize-space($text-value) = ''">
<xsl:message terminate="yes">
<xsl:call-template name="output_message3_fail">
<xsl:with-param name="parent_node" select="name(parent::node())"/>
</xsl:call-template>
</xsl:message>
</xsl:if>
<xsl:value-of select="$text-value"/>
</xsl:template>
但是,我发现输入是否如下所示:
<dataset>
<title>My tile</title>
</dataset
将调用新的文本模板。如果输入看起来像:
<dataset>
<title> </title>
</dataset>
永远不会调用新的文本模板,输出看起来像
<dataset>
<title/>
</dataset>
所以我的方法 - 修改文本模板,不起作用。您对如何执行此操作有任何建议吗 - 如果找到一个包含空字符串的元素,则终止转换。
非常感谢!
顺便说一下,我正在使用 java xalan xslt 处理器。
最佳答案
However, i found out if input looks like:
<dataset> <title>My tile</title> </dataset>
the new text template will be called
是的,这正是提供的代码应该做的——我稍后会对此进行解释。
If input looks like:
<dataset> <title> </title> </dataset>
the new text template will never be called and output will looks like
<dataset> <title/> </dataset>
我无法用 Xalan(J 或 c)和许多其他 XSLT 处理器重现这个我有(Saxon 6.5.3、.NET XslCompiledTransform 和 XslTransform、Msxml3、4、6、JD、 ... ETC)。 它们都显示一条错误消息(在 <xsl:message terminate="yes">
内)
产生上述输出的唯一 XSLT 处理器是 AltovaXML (XmlSPY)。
如果您正在使用 XmlSPY,您可能会考虑尝试使用其他 XSLT 处理器或联系 Altova 寻求帮助。
现在,回到第一个行为。
解释:
提供的源 XML 文件:
<dataset>
<title>My tile</title>
</dataset>
具有三个文本节点:
第一个文本节点是
<dataset>
之间的节点。和<title>
它只包含空格。第二个文本节点是
<title>
的唯一子节点它的值是字符串“My tile”。第三个和最后一个文本节点介于
</title>
之间和</dataset>
并且只包含空格。
当模板匹配text()
被选中用于处理上述三个文本节点中的第一个,测试为正且<xsl:message terminate="yes">
被执行——这正是报告的行为。
解决方案:
存在一个简单的解决方案。 只需更改模板匹配text()
仅匹配作为其父节点的唯一文本节点的文本节点。现在,对于最初提供的两种类型的 XML 文档,XSLT 转换的行为符合预期:
<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="*">
<xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match=
"*[not(node()[2])]/text()
[normalize-space()='']">
<xsl:message terminate="yes">
<xsl:call-template name="output_message3_fail">
<xsl:with-param name="parent_node" select="name(..)"/>
</xsl:call-template>
</xsl:message>
</xsl:template>
<xsl:template name="output_message3_fail">
<xsl:param name="parent_node"/>
<xsl:message> ERROR:
<<xsl:copy-of select="$parent_node"/>> is empty
</xsl:message>
</xsl:template>
</xsl:stylesheet>
在提供的 XML 文档上应用此转换时:
<dataset>
<title>My tile</title>
</dataset>
产生了想要的结果:
<dataset>
<title>My tile</title>
</dataset>
应用于第二个XML文档时:
<dataset>
<title> </title>
</dataset>
产生了正确的结果:
ERROR:
<title> is empty
关于java - xsl中如何找出空字符串值的元素节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/544153/