XSLT 2.0处理无效节点混合文本和CDATA

问题描述:

我需要解析以下节点: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

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

当XSLT处理器看到文本时,CDATA消失了。您无法看到传入的CDATA,并且几乎无法控制如何生成输出CDATA(对于给定标记全部或全部没有)。

无法在标准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