xml - 如何在元素中检测文本节点

标签 xml xslt xpath

嗨,我有以下问题:

我需要检测某些元素中是否有子文本节点,但不包括前导和尾随空格,回车,制表符和换行符。任何“空白”空间都不会计入文字。

我发现此函数normalize-space()对我来说部分起作用。但是,如果将文本节点放置在嵌套元素之后,则函数将找不到它。例如:

<list>
   <list-item/>
   This is the text node
</list>


因此,当当前上下文匹配时,<list>元素<xsl:value-of select="noramalize-space(text())"/>返回空字符串。但是它应该返回“ This is the text node”,不是吗?

这是我正在尝试的代码:

.xml:

<catalog>
    <cd>
        <empty-element>
            <nested-empty-element/>
        </empty-element>
        <title>Empire Burlesque</title>
        <list>
            <list-itme>
                <bullet>This is bullet</bullet>
            </list-itme>
        This is the text node
        </list>
        <artist>Bob Dylan</artist>
    </cd>
</catalog>


.xsl:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml"/>
    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="/catalog/cd"/>
        </root>
    </xsl:template>
    <xsl:template match="cd">
        <xsl:apply-templates select="*"/>
    </xsl:template>
    <xsl:template match="*">
        <xsl:if test="normalize-space(text())">
            <para>
            <xsl:value-of select="."/>
            </para>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>


转换后,我得到以下结果:

<root>
    <para>Empire Burlesque</para>
    <para>Bob Dylan</para>
</root>


问题是:为什么我没有得到这个结果?:

<root>
    <para>Empire Burlesque</para>
    <para>This is the text node</para>
    <para>Bob Dylan</para>
</root>


为什么不处理list元素,它也具有文本节点?

最佳答案

这是因为list之前在list-itme下有一个空格文本节点(我添加了注释以显示位置。从技术上讲,您将为下面的XML有两个空格节点。一个在注释之前,然后是一)

    <list>        <!-- Whitespace text node here -->
        <list-itme>
            <bullet>This is bullet</bullet>
        </list-itme>
    This is the text node
    </list>


如果要忽略这些空白节点,则可以使用xsl:strip-space命令忽略它们

<xsl:strip-space elements="*" />


试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml"/>
    <xsl:strip-space elements="*" />
    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="/catalog/cd"/>
        </root>
    </xsl:template>
    <xsl:template match="cd">
        <xsl:apply-templates select="*"/>
    </xsl:template>
    <xsl:template match="*">
        <xsl:if test="normalize-space(text())">
            <para>
            <xsl:value-of select="normalize-space(text())"/>
            </para>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>


或者,可以通过对normalize-space不为空的任何文本节点进行测试来获得相同的结果(您的当前表达式正在对第一个文本节点进行规范化)

 <xsl:if test="text()[normalize-space()]">


也尝试一下

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml"/>
    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="/catalog/cd"/>
        </root>
    </xsl:template>

    <xsl:template match="cd">
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:if test="text()[normalize-space()]">
            <para>
            <xsl:value-of select="normalize-space(text()[normalize-space()])"/>
            </para>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

关于xml - 如何在元素中检测文本节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34038663/

相关文章:

c# - 将 CSS 选择器转换为 XPATH

xml - 如何让 IXmlDomDocument2.XML 正确转义引号?

java - JAXB xml 写在一行上。我该如何格式化

xml - 仅在 xslt 中对单例标签进行模式匹配

xml - 将 <span> 标签添加到自定义自闭合标签之间的所有文本节点

xslt - 仅输出文本没有具有特定值的子节点

python - 基于多个相邻值的 XPATH

xml - 如何在Powershell中使用冒号读取xml属性

xml - 保留 xml 编码 XSLT

xml - 如何使用 XPATH 从 XML 文档中选择不同的值?