在使用XPath的复杂XML元素中的空白文本节点中选择子文本节点
我一直在绞尽脑汁想这个问题,但似乎没有弄对,而且我没有在谷歌上找到正确的关键词 我最近开始使用XSLT和XPath来创建自然语言词汇表的XML描述——这是我的一个项目 问题是,我选择对某些单词使用“混合内容”复杂元素,在某些情况下,我只想获取文本节点 以下是XML文档的一部分:在使用XPath的复杂XML元素中的空白文本节点中选择子文本节点,xml,xslt,xpath,Xml,Xslt,Xpath,我一直在绞尽脑汁想这个问题,但似乎没有弄对,而且我没有在谷歌上找到正确的关键词 我最近开始使用XSLT和XPath来创建自然语言词汇表的XML描述——这是我的一个项目 问题是,我选择对某些单词使用“混合内容”复杂元素,在某些情况下,我只想获取文本节点 以下是XML文档的一部分: ... <entry category="substantiv"> <word lang="sv">semester</word> <word lang="de">
...
<entry category="substantiv">
<word lang="sv">semester</word>
<word lang="de">
<article>der</article>Urlaub
<plural>Urlaube</plural>
</word>
</entry>
...
我想我要做的是选择word[@lang='de']的所有直接文本节点,然后使用normalize-space()
删除不必要的空白。但是,如何使用XPath实现这一点?还是有更好的办法?看起来很容易,但我想不出来。顺便说一下,我正试图在XSLT文档中实现这一点
规范化空间(/entry/word[@lang='de']/text()[*])
是我尝试过的事情之一,但这似乎起到了其他作用
/谢谢你的帮助
更新:
以下是XSLT的一部分,根据要求:
...
<xsl:choose>
<xsl:when test="@category='substantiv'">
<em><xsl:value-of select="word[@lang='de']/article" /></em>
<xsl:value-of select="normalize-space(word[@lang='de']/text()[2])" />
<em>pl. <xsl:value-of select="word[@lang='de']/plural" /></em>
</xsl:when>
...
。。。
pl。
...
这段代码与格式化的第一个版本配合得很好。为了澄清,我想做的是绘制复杂元素
中文本节点的值,尽管它的格式可能是换行符和空格。我将如何处理该值取决于上下文,但现在我将把它放在一个xhtml文档中
更新2:
我现在使用
,它消除了空文本节点的问题。我还使用:
...
<xsl:choose>
<xsl:when test="@category='substantiv'">
<em><xsl:value-of select="word[@lang='de']/article" /></em>
<xsl:text> </xsl:text>
<xsl:value-of select="normalize-space(word[@lang='de']/text())" />
<xsl:text>, </xsl:text>
<em>pl. <xsl:value-of select="word[@lang='de']/plural" /></em>
</xsl:when>
...
。。。
,
pl。
...
但是仍然需要规范化,因为XML中的“Urlaub”后面仍然添加了空格
当我需要到达XSLT文档外部的文本节点“Urlaub”时,我使用:
谢谢大家的帮助
更新3:
尝试改进标题现在我看到了您的代码,我建议:
<xsl:choose>
<xsl:when test="@category='substantiv'">
<em><xsl:value-of select="word[@lang='de']/article" /></em>^
<!-- select the first non-empty text node and normalize it -->
<xsl:value-of select="normalize-space(word[@lang='de']/text()[normalize-space() != ''][1])" />
<em>pl. <xsl:value-of select="word[@lang='de']/plural" /></em>
</xsl:when>
^
pl。
答案的原始版本 要开始,请执行以下操作:
<entry category="substantiv">
<word lang="sv">semester</word>
<word lang="de">
<article>der</article>Urlaub
<plural>Urlaube</plural>
</word>
</entry>
学期
德鲁拉布
乌拉贝
通过此XSLT 1.0时:
<!-- identity template copies everything 1:1, unless other templates apply -->
<xsl:template match="*|@*">
<xsl:copy>
<xsl:apply-templates select="*|@*" />
</xsl:copy>
</xsl:template>
<!-- empty template: ignore every white-space-only text-node child of <word> -->
<xsl:template match="word/text()[normalize-space() = '']" />
将产生以下结果:
<entry category="substantiv">
<word lang="sv">semester</word>
<word lang="de"><article>der</article>Urlaub<plural>Urlaube</plural></word>
</entry>
学期
德鲁劳布劳贝
这个答案只是猜测,可能并不完全是你想要的。你的问题无论如何都需要澄清。并非总是你认为你想要的和你实际想要的一样。试试:
/entry/word[@lang='de']/child::text()[normalize-space(.) != '']
也就是说,抓取所有子文本节点,但不要抓取那些规范化为空字符串的子文本节点
-Oisin我认为这是你想要的东西的骨架,减去任何normalize-space(),让东西看起来完全像你想要的那样
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates select=".//word"/>
</xsl:template>
<xsl:template match="word">
<xsl:apply-templates select=".//text()"/>
</xsl:template>
<xsl:template match="text()"><xsl:value-of select="."/><xsl:text> </xsl:text></xsl:template>
</xsl:stylesheet>
关键是//text()
,它返回上下文节点()下任何嵌套级别的所有子文本节点的连接。此转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:value-of select="/*/entry/word[@lang='de']/text()[1]"/>
</xsl:template>
</xsl:stylesheet>
准确地生成所需的结果:
Urlaub
注意事项:使用
指令从源XML文档中删除所有纯空白文本节点
因此,不需要额外的处理(normalize-space()等)如果没有相关的XSLT上下文,就无法自信地回答这个问题。请在您的问题中添加您正在努力解决的XSLT代码,以及您的实际意图(即想要的输出)。@Tomalak,我不是在努力解决XSLT问题,只是XPath部分。但我添加了它,以防它可能会提供一些必要的信息。您不必为XSLT而烦恼,这是另外一点展示您的代码是有帮助的,因为XSLT和XPath密切相关,许多问题的解决方案可能与您当前尝试的不同看我改变的答案。是的,你完全正确。XML打开了一个全新的奇妙世界,但有时它会让人非常困惑:)提及
子::
轴是多余的。另外,默认情况下,normalize-space()
在当前节点上运行,因此无需在
中提及它。键入word[@lang='de']/text()[normalize-space()!=''即可。谢谢啊,是的,我一点也不清楚。我不想改变格式化,只想处理不同的格式化场景。但是你在其他方面帮了我,所以你的回答仍然有用。谢谢!:)@你有没有注意到我的答案的上半部分发生了变化?是的,我注意到了,这种变化起了作用。谢谢你的帮助。虽然我现在有点困惑text()到底应该如何工作,但如果我不能弄清楚,我明天会开始一个新问题。@nimbus:text()
是,尽管有括号,但不是函数。至少不是你想象的那样。它选择文本节点,就像foo
选择
元素一样。括号是将它与文本
分开的一种方式,后者将选择
元素。是的,我被它愚弄了。我今天还发现它被称为节点测试。我还认为它会自动将文本节点连接成一个字符串,就像我在XPath末尾加上:word[@lang=“de”]
一样。但是,现在我更清楚了。:)这就是我认为//text()
对。。也许我做错了?如果我使用
(虽然还没有开始使用模板),我什么也得不到。但是如果我在XPath计算器中测试它,它会发现5个可能的文本节点,因为还添加了'der'和'Urlaube'。“关键是返回所有子文本节点的串联的//text()
”——实际上,这是错误的//text()
选择所有的文本节点,它返回一组单独的节点,而不是串联的字符串。这是一个真正的nic
<dict>
<entry category="substantiv">
<word lang="sv">semester</word>
<word lang="de">
<article>der</article>Urlaub
<plural>Urlaube</plural>
</word>
</entry>
</dict>
Urlaub