Java 如何在xsl中查找具有空字符串值的元素节点
我正在将xml文件从旧版本转换为新版本。以下是我正在使用的基本模板:Java 如何在xsl中查找具有空字符串值的元素节点,java,xml,xslt,xpath,xsd,Java,Xml,Xslt,Xpath,Xsd,我正在将xml文件从旧版本转换为新版本。以下是我正在使用的基本模板: <xsl:template match="*"> <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}"> <xsl:copy-of select="@*"></xsl:copy-of> <xsl:apply-templates></xsl:apply-templa
<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>
然而,新版本的XMLSchema要求所有具有文本值的元素不应为空字符串。旧的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> </title>
</dataset>
我的瓷砖
然而,我发现输入是否
比如:
在提供的XML文档上应用此转换时:
<dataset>
<title>My tile</title>
</dataset>
我的瓷砖
产生所需结果:
<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>
<dataset>
<title>My tile</title>
</dataset>
<dataset>
<title> </title>
</dataset>
我的瓷砖
应用于第二个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="*">
<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>
<dataset>
<title>My tile</title>
</dataset>
<dataset>
<title> </title>
</dataset>
产生正确的结果:
ERROR:
<title> is empty
错误:
是空的
我不清楚你到底想要什么。您表示不希望发出包含空字符串的元素,然后给出以下示例:
<dataset>
<title> </title>
</dataset>
此模板将匹配符合以下条件的任何元素:
- 它没有子元素
- 它至少包含一个文本节点
- 它包含的所有文本节点仅为空白
因此,在您的示例中,它将与数据集
元素不匹配(因为它有一个子元素),但它将与标题
元素匹配。但是,它与
或
不匹配,因为这两个元素都不包含文本节点。也许测试应该是这样的
length(text())!=0 && length(strip-whitespace(text())) == 0
xslt不支持正则表达式吗?如果是这样的话,那就应该这样做
但他是否希望每个元素都必须包含一些非空间文本?或者有一些元素必须至少包含某些内容,而其他元素
<foo bar="BAR"/>
行吗?我敢打赌这是什么。我认为,他很可能不得不为那些必须是非空的元素逐个编写ULE
这就引出了我的最后一点意见:检查XML文档有效性的正确技术是XML模式。规范化空间是否与strip space相同(在XPATH 1.0中也受支持?@geoffc No,normalize-space()是一个可用于作用于文本节点值的函数,不是为了使节点不可读,我很困惑。xsl:strip space从源树中删除仅空白的文本节点。那么,在什么情况下,模板匹配text()节点可以发出消息?它测试的所有文本节点都已从源代码树中删除。我已经解释了OP报告的两个问题中的第一个,并提供了解决方案。请稍等几分钟,第二个问题将在@Robert Rossney的上下文中处理,谢谢您指出这一点。我编辑了解决方案以适应这两种情况。解释是一样的。@Robert Rossney谢谢你指出这一点。我编辑了解决方案以适应这两种情况。罗伯特·罗斯尼:“空字符串”的意思是“仅限空白”。你的模板符合我的要求。非常感谢你!还有,谢谢你,迪米特里·诺瓦切夫@罗伯特·罗斯尼我不明白你的说法。你能举个例子吗?使用谷歌提供的我的用户名emai@RobertRossney正确,数学模式必须是:“*[not(node()[2])]/text()[normalize-space()=''”,而不是“*[not(text()[2])]]/text()[normalize-space()=''”,我已经用所有已知的XML文档测试过了,没有问题。编辑了答案。谢谢
length(text())!=0 && length(strip-whitespace(text())) == 0
<foo bar="BAR"/>