java - xsl中如何找出空字符串值的元素节点

标签 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-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>

具有三个文本节点:

  1. 第一个文本节点是<dataset> 之间的节点。和 <title>它只包含空格。

  2. 第二个文本节点是 <title> 的唯一子节点它的值是字符串“My tile”。

  3. 第三个和最后一个文本节点介于 </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:        
      &lt;<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/

相关文章:

java - 在另一个类中将用户输入变量相乘,然后将结果命名为变量

java - 如何在同一测试中使用 Appium 从 Android 内存中硬关闭/强制关闭/终止应用程序

java - java类设计指南

python - 在Python中使用lxml解析XML文件

java - 转换性能 XML>XSL>XML 与 XML>JAXB>XML

java - 使 Dialog 在 AsyncTask 完成后关闭

xml - 如何提高 VBA 中 XML 解析的速度

java - Android:尝试向我的应用程序添加另一种语言后出现 Inflate 异常

xslt - DITA XSLT - 将元标记编写为关键字

xml - IF 语句是否允许 XSLT 中的 OR 条件?