2010-11-16 51 views
1

我需要解析以下節點:XSLT 2.0處理無效節點混合文本和CDATA

<media:keywords>keyword1,keyword2<![CDATA[keyword3]]></media:keywords> 

成有效的串,優選「關鍵字1,關鍵字2,KEYWORD3」,但我會滿足於完全除去CDATA。

試圖訪問該節點給我的文字「keyword1,keyword2keyword3」,我不能告訴CDATA開始的地方。

原始的XML(簡化mRSS資訊版)

<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"> 
    <channel> 
    <item> 
     <media:keywords>keyword1,keyword2<![CDATA[keyword3]]></media:keywords> 
    </item> 
    </channel> 
</rss> 

XSL(簡體):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:media="http://search.yahoo.com/mrss/" exclude-result-prefixes="xs xsi fn"> 
    <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/> 
    <xsl:template match="/"> 
     <test> 
      <xsl:variable name="items" select="/rss/channel/item"/> 
      <xsl:for-each select="$items"> 
       <xsl:variable name="mediakw" select="media:keywords"/> 
       <xsl:element name="mediaKeyWords"> 
         <xsl:value-of select="$mediakw"/> 
       </xsl:element> 
      </xsl:for-each> 
     </test> 
    </xsl:template> 
</xsl:stylesheet> 

和輸出:

<test xmlns:media="http://search.yahoo.com/mrss/"><mediaKeyWords>keyword1,keyword2keyword3</mediaKeyWords></test> 

非常感謝!

+1

如果您分別使用Saxon和XSLT 2.0處理器的Java實現,請查看將http://andrewjwelch.com/lexev/插入到處理鏈中,這樣可以將CDATA部分更改爲標記,然後XSLT處理器可以操作。 – 2010-11-16 17:54:24

回答

2

XML和XSLT不能幫你在這裏

XSLT使用INFOSET模型,其中有沒有什麼作爲 「CDATA節點」和存在的僅僅是單個文本()節點:

「關鍵字,keyword2keyword3」

的XML文檔需要校正和逗號的子串"keyword2""keyword3"

一種解決方案之間插入處理CDATA DOM節點使用DOM,然後才啓動XSLT轉換。

+0

另外XDM也是如此。 – 2010-11-16 17:49:16

+0

+1好點。我不知道DOM提供CDATASection作爲可選的「擴展接口」。我想知道哪些處理器支持。 – LarsH 2010-11-16 19:28:34

+0

@LarsH:MSXML和.NET XmlReader(NodeTypeEnumeration) – 2010-11-16 19:36:54

2

當XSLT處理器看到文本時,CDATA消失了。您無法看到傳入的CDATA,並且幾乎無法控制如何生成輸出CDATA(對於給定標記全部或全部沒有)。

2

無法在標準XSLT中完成。

輸入XML您收到,

<media:keywords>keyword1,keyword2<![CDATA[keyword3]]></media:keywords> 

是沒有區別(以XSLT)從

<media:keywords>keyword1,keyword2keyword3</media:keywords> 

因爲CDATA標記是逃避它裏面的數據的只是一種方法。在這種情況下,確實沒有特別的標記可以逃脫,所以CDATA恰好是沒有操作的。但是XSLT無法知道最初使用CDATA表達了什麼數據,使用字符實體表達了什麼等等。

解決方法是告訴誰提供這個XML,他們需要在關鍵字2和關鍵字3之間加上一個分隔符。

+0

@LarsH:不僅可以區分爲XSLT,還可以按照@ Dimitre指出的Infoset規範或現代XDM,爲每個XML樹提供程序區分開來。 – 2010-11-16 17:48:04

+0

@Alejandro:對(雖然XML語言/工具規範*可以*使用有關CDATA部分的信息,而不會實際違反Infoset規範......請參閱http://www.w3.org/TR/xml-infoset/#conformance,第3項)。我指定了XSLT,因爲OP詢問了一個XSLT解決方案。 – LarsH 2010-11-16 18:05:06

+0

@LarsH:是的,一個實現可以擴展Infoset,但標準**明確**在http://www.w3.org/TR/xml-infoset/#omitted中說:*以下信息未在當前版本的XML信息集:19. CDATA標記的區域的邊界* – 2010-11-16 18:13:48