Java 如何在xsl中查找具有空字符串值的元素节点

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

我正在将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>

然而,新版本的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:        
      &lt;<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:        
      &lt;<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"/>