2011-11-20 32 views
0

的输出流量如何使一个XSLT转换这样的:打破在XSLT

<root> 
<element>This 
    <element>is</element> 
</element> 
<element>normal!</element> 
<element>This</element> 
<element>will 
    <special>break here</special> 
    <element>and 
    <element>also 
    <special>here!</special> 
    </element> 
    </element> 
</element> 
</root> 

进入这个:

<root> 
<content>This is normal! This will</content> 
<special>break here</special> 
<content>and also</content> 
<special>here!</special> 
</root> 

考虑<special>可以出现任何数量的时间和任何地方。我想我需要处理文件两次才能做到这一点,但我需要立即执行。

编辑:只是一个澄清,它不是一个简单的副本,内容也从一端转换到另一端(为什么我认为我需要两个不同的转换)。

EDIT2:这里是我想要的算法:

1)去等待处理的所有元素,直到你找到一些特别的元素,把它全部到目前为止里面<content>

2)如果下一个元素是特殊的将其放在<specialContent>

3)如果有些事转到步骤1

编辑3我改变了我的示例xml,使其更清晰。

+0

这取决于你在看什么样的转换,这可能是可能的 – prusswan

回答

0

Dimitri的答案非常好,但由于生成的内容和非常深的模板层次结构,它会破坏我的XSLT中的一些东西。

这里是解决方案,我最终使用:

首先我所有的正常处理,那么我所说的后处理:

<xsl:variable name="content"> 
    <xsl:apply-templates /> 
</xsl:variable> 
<xsl:apply-templates select="msxsl:node-set($content)" mode="postProcess" /> 

在后处理它搜索任何东西,不是div的类属性中带有WideContent标记,并将相邻的同胞分组在另一个div内,那些具有WideContent标记的同辈只是简单地复制(但也可以以相同的方式组合)。

<xsl:template match="/*[not(self::xhtml:div[contains(@class,'WideContent')])][preceding-sibling::*[1][self::xhtml:div[contains(@class,'WideContent')]] or position()=1]" mode="postProcess"> 
    <div class="NormalContent"> 
    <xsl:call-template name="postProcessNormalContent" /> 
    </div> 
</xsl:template> 

<xsl:template name="postProcessNormalContent" match="/*[not(self::xhtml:div[contains(@class,'WideContent')])]" mode="postProcessNormalContent"> 
    <xsl:copy-of select="."/> 
    <xsl:apply-templates select="following-sibling::*[1]" mode="postProcessNormalContent" /> 
</xsl:template> 

<xsl:template match="xhtml:div[contains(@class,'WideContent')]" mode="postProcess"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template match="node()" mode="postProcess" /> 
<xsl:template match="node()" mode="postProcessNormalContent" /> 

任何有关如何改进的建议将很乐意采取。

0
<xsl:template match="@* | node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="content//*[not(self::SpecialContent)]"> 
    <xsl:apply-templates/> 
</xsl:template> 

应该就足够了。

+0

我的不好,实际上内容发生了各种转换,所以它不是简单的副本。 –

0
<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="root"> 
     <content> 
      <xsl:copy-of select=".//content/text()[following-sibling::node()[1][self::subcontent]]" /> 
      <xsl:copy-of select=".//subcontent/text()[following-sibling::node()[1][self::subsubcontent]]" />   
      <xsl:copy-of select=".//subsubcontent/text()[following-sibling::node()[1][self::SpecialContent]]" />    
     </content> 
     <xsl:for-each select=".//SpecialContent"> 
      <xsl:copy-of select="." /> 
     </xsl:for-each> 
     <content> 
      <xsl:copy-of select=".//subsubcontent/text()[preceding-sibling::node()[1][self::SpecialContent]]" /> 
      <xsl:copy-of select=".//subcontent/text()[preceding-sibling::node()[1][self::subsubcontent]]" /> 
      <xsl:copy-of select=".//content/text()[preceding-sibling::node()[1][self::subcontent]]" /> 
     </content> 
    </xsl:template> 
    <xsl:template match="text()" /> 
</xsl:stylesheet> 

不是很漂亮,但应与其他转换工作,如果任何

+0

不完全如我所说,Special可以在任何地方和任何次数。 –

+0

好吧我看到您的修改后的问题,因此我的答案不再适用 – prusswan

0

我认为你可以做到这一点的一个方法是把所有的元素*元素由第一**特殊元素是或者后代或以下元件,

<xsl:key name="content" 
    match="element" 
    use="generate-id((descendant::special|following::special)[1])" /> 

然后可以通过

0123的文档中的所有 调校妥当元件匹配开始
<xsl:apply-templates select="//special" /> 

并为每个特殊元素,你匹配,然后你可以组在一起的所有相关元素有这个当前元素作为其第一个decendant或以下元素的元素。

<content> 
    <xsl:apply-templates select="key('content', generate-id())" /> 
</content> 

因此,考虑到下面的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:key name="content" 
     match="element" 
     use="generate-id((descendant::special|following::special)[1])" /> 

    <xsl:template match="/root"> 
     <xsl:copy> 
     <xsl:apply-templates select="//special" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="special"> 
     <content> 
     <xsl:apply-templates select="key('content', generate-id())" /> 
     </content> 
     <xsl:copy-of select="." /> 
    </xsl:template> 

    <xsl:template match="element"> 
     <xsl:value-of select="normalize-space(text())" /><xsl:text> </xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 

当适用于您的示例XML,下面是输出

<root> 
    <content>This is normal! This will </content> 
    <special>break here</special> 
    <content>and also </content> 
    <special>here!</special> 
</root> 

(请注意,在每个内容的后面加上一个空格标签,但如果需要,我可以轻松调整XSLT以将其删除)。

2

看来,在这个时候所有现有的答案无意中发现这个XML文档上:

<root> 
    <element>This 
     <element>is</element></element> 
    <element>normal!</element> 
    <element>This</element> 
    <element>will 
     <special>break here</special> 
     <element>and  
      <element>also  
       <special>here!</special> 
      </element> 
     </element> 
     <element>But not here</element> 
    </element> 
</root> 

下面是正确处理它转换:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:key name="content" match="element" 
    use="generate-id((ancestor::special|preceding::special)[last()])"/> 

<xsl:template match="/*"> 
    <xsl:copy> 
    <content> 
     <xsl:apply-templates select="key('content', '')"/> 
    </content> 
    <xsl:apply-templates select="//special" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="special"> 
    <xsl:copy-of select="." /> 
    <content> 
    <xsl:apply-templates select= 
     "key('content', generate-id())" /> 
    </content> 
</xsl:template> 

<xsl:template match="element"> 
    <xsl:value-of select="normalize-space(text())" /> 
    <xsl:text> </xsl:text> 
</xsl:template> 
</xsl:stylesheet> 

当应用在上面的XML文档中,生成了想要的正确结果

<root> 
    <content>This is normal! This will </content> 
    <special>break here</special> 
    <content>and also </content> 
    <special>here!</special> 
    <content>But not here </content> 
</root> 
+0

这真的会起作用,但我认为我的问题只是出了问题,有太多的内容正在转变以跟踪所有内容,我也得到了一些自动生成的如果我使用这种处理,会丢失内容。我想解决方案是另一个XSLT(流水线)或创建一个变量的内容,并使用node-set()将它传递给另一个模板... –

+0

@LuizBorges:是的,这个处理总是可以在一个单独的过程中完成。如果您在如何执行此操作时遇到问题,请搜索xslt标签 - 有几个问题可以解答如何进行多通道处理。 –

+0

@LuizBorges:查看两遍转换的示例:http://stackoverflow.com/questions/3678353/apply-xslt-transform-to-an-already-transformed-xml/3678779#3678779 –