2010-08-09 97 views
1

我一直在绞尽脑汁,但似乎无法正确使用,而且我没有找到正确的关键字Google ..在使用XPath的复杂XML元素中选择白色空间文本节点中的子文本节点

我最近开始使用XSLT和XPath来创建自然语言词汇表的XML描述 - 用于我的项目。

问题是我选择了对某些单词使用“混合内容”复杂元素,并且在某些情况下只想获取文本节点。

这里的XML文档的一部分:

... 
<entry category="substantiv"> 
    <word lang="sv">semester</word> 
    <word lang="de"> 
    <article>der</article>Urlaub 
    <plural>Urlaube</plural> 
    </word> 
</entry> 
... 

有我的文档中的许多入门元素,在这种情况下我想通过获取“Urlaub”:/entry/word[@lang='de']/text()这是因为我的换行符的,不会工作。我发现实际上有三个文本节点.. .../text()[2]当然会工作..但是,我不知道哪里会有换行符,或者有多少。如果XML被格式化像下面,我该路径的第一个版本将工作,但不是第二:

... 
<word lang="de"><article>der</article>Urlaub 
    <plural>Urlaube</plural> 
</word> 
... 

我觉得我想要做的是选择所有字的直接文本节点[@ LANG =” de'],然后使用normalize-space()删除不必要的空白区域。但是,如何使用XPath执行此操作?或者,还有更好的方法?这似乎很容易,但我无法弄清楚。我正在尝试在XSLT文档中执行此操作。

normalize-space(/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> 
... 

此代码工作得很好用格式化的第一个版本。为了澄清,我想要做的是对复杂元素<word lang="de">中的文本节点的值进行绘图,尽管可能会用换行符和空格来格式化。我将如何处理价值取决于上下文,但现在我将它放在一个xhtml文档中。

UPDATE2: 我现在用的<xsl:strip-space elements="*"/>这消除了空文本节点的问题。我也使用:

... 
<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> 
... 

还是要正常化,虽然由于空间的XML“Urlaub”后,仍然增加。

当我需要达到的文本节点“Urlaub”的XSLT文档之外我用:
<xsl:value-of select="normalize-space(word[@lang='de']/text()[normalize-space() != ''])" />

感谢所有帮助乡亲!

更新3: 试图改善标题

+0

如果没有相关的XSLT上下文,就无法自信地回答。请添加您正在努力解决的问题的XSLT代码以及您的实际意图(即所需输出)。 – Tomalak 2010-08-09 18:50:17

+0

@Tomalak,我没有在XSLT,只有XPath部分挣扎。但我补充说,以防万一它可能摆脱一些需要的光。 – nimbus77 2010-08-09 20:57:15

+0

除了重点之外,你并没有在XSLT中挣扎。 ;)显示你的代码是有帮助的,因为XSLT和XPath是如此密切相关,许多问题可能有与你目前尝试的不同的解决方案。 - 看到我改变的答案。 – Tomalak 2010-08-09 21:11:09

回答

2

这种变换:

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

当所提供的XML文档(包裹在dict顶部元件)施加:

<dict> 
    <entry category="substantiv"> 
     <word lang="sv">semester</word> 
     <word lang="de"> 
      <article>der</article>Urlaub 
      <plural>Urlaube</plural> 
     </word> 
    </entry> 
</dict> 

正好产生想要的结果

Urlaub 

请注意:使用<xsl:strip-space>指令从源XML文档中消除所有只包含空格的文本节点。

因此,不需要额外的处理(normalize-space()等)

+0

这是一个非常好的解决方案。 Vielen Dank! :) – nimbus77 2010-08-09 21:53:17

+0

原来“Urlaub”后面仍有空白,但这不是问题。 – nimbus77 2010-08-09 22:45:04

+0

删除了空白节点,即仅包含空白字符的文本节点。 “Urlaub”文本节点包含非空白字符,因此它不受的影响。 – Ags1 2017-12-21 14:03:45

0

现在,我看到你的代码,我建议这样的:

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

原始答案的版本

为了让你开始:

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

这个答案是猜测,可能不正是你所追求的。无论如何你的问题需要澄清。并不总是你想要的认为你想要的与你实际上想要的一样。

+0

啊,是的,我一点也不清楚。我不想改变格式,只处理不同格式的格式。但是你帮助了我一些其他的东西,所以你的答案仍然有用。谢谢! :) – nimbus77 2010-08-09 21:26:48

+0

@nimbus:你有没有注意到我答案的最后部分改变了? – Tomalak 2010-08-09 21:37:26

+0

是的,我做了,这个改变就是诀窍。感谢您的帮助。 虽然至于text()应该如何工作,但我现在有点困惑,但如果我无法弄清楚,我明天将开始一个新的问题。 – nimbus77 2010-08-09 21:58:17

0

尝试:

/entry/word[@lang='de']/child::text()[normalize-space(.) != ''] 

意义,抓住所有子文本节点,但不是那些正常化为空字符串。

-Oisin

+0

提到'child ::'轴是多余的。另外,默认情况下,'normalize-space()'在当前节点上运行,所以通过'.'提到它是没有必要的。 – Tomalak 2010-08-09 18:53:13

+0

输入字[@ lang ='de']/text()[normalize-space()!='']这样做。谢谢! – nimbus77 2010-08-09 21:20:26

0

我想这是你想要的骨架,减去正常化空间()得到的东西看起来正是你想要的方式。

<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()()。

+0

这就是我认为'.// text()'会做..也许我做错了吗? 如果我使用''(还没有开始使用模板, )我什么也没得到。但是如果我在我的XPath评估器中测试它,它会发现5个可能的文本节点,因为'der'和'Urlaube'也被添加。 – nimbus77 2010-08-09 21:41:45

+0

*“关键是'。text()',它返回所有子文本节点的连接”* - 实际上,这是错误的。 ''text()'*选择*所有文本节点,它返回一个节点集合的单独节点,而不是连接字符串。 – Tomalak 2010-08-10 12:02:58

相关问题