2010-08-09 73 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

相關問題