2010-09-23 56 views
1

我正在尝试编写将选择某种类型的直接兄弟的XSLT,但在到达其他标记时停止。使用xslt将平板xml解释为嵌套xhtml

这里的源XML:

<?xml version="1.0"?> 
<body> 
    <proc>Test</proc> 
    <alert>Test1: alert 1</alert> 
    <alert>Test1: alert 2</p> 
    <para>Test para 1</para> 
    <alert>Test2: alert 1</alert> 
    <alert>Test2: alert 2</alert> 
    <alert>Test2: alert 3</alert> 
    <proc>Test</proc> 
    <alert>Test3: alert 1</alert> 
    <alert>Test3: alert 2</alert> 
    <alert>Test3: alert 3</alert> 
</html> 

这里是预期的结果:

<?xml version="1.0" encoding="UTF-8"?> 
<body> 
    <proc> 
     <alert>Test1: alert 1</alert> 
     <alert>Test1: alert 2</alert> 
    </proc> 
    <para>Test para 1</para> 
    <alert>Test2: alert 1</alert> 
    <alert>Test2: alert 2</alert> 
    <alert>Test2: alert 3</alert> 
    <proc> 
     <alert>Test3: alert 1</alert> 
     <alert>Test3: alert 2</alert> 
     <alert>Test3: alert 3</alert> 
    </proc> 
</body> 

是这甚至可能吗?

这是我这是不是做的伎俩当前的xsl:如果您正在使用XSLT 2类似下面应该工作

<xsl:template match="proc"> 
    <xsl:variable name="procedure" select="."/> 
    <xsl:apply-templates/> 
    <xsl:for-each 
    select="following-sibling::alert[preceding-sibling::proc[1] = $procedure]"> 
     <xsl:apply-templates select="."/> 
    </xsl:for-each> 
</xsl:template> 


<xsl:template match="c:hhtAlert">...</xsl:template> 

<xsl:template match="c:hhtPara">...</xsl:template> 
+0

您使用的是XSLT 1还是2? – 2010-09-23 10:26:28

+0

好问题(+1)。请参阅我的答案,了解XSLT 1.0解决方案的高效和简短。 :) – 2010-09-23 13:03:26

回答

0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="body"> 
    <xsl:copy> 
     <xsl:for-each-group select="*" group-starting-with="para | proc"> 
     <xsl:choose> 
      <xsl:when test="self::para"> 
      <xsl:apply-templates select="current-group()"/> 
      </xsl:when> 
      <xsl:otherwise> 
      <xsl:copy> 
       <xsl:apply-templates select="current-group()[position() &gt; 1]"/> 
      </xsl:copy> 
      </xsl:otherwise> 
     </xsl:choose> 
     </xsl:for-each-group> 
    </xsl:copy> 
    </xsl:template> 

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

检查这是输出错误的结果。 – 2010-09-23 13:38:35

+0

@Alejandro:对不起,意思是团队开始。并添加身份转换以使其完成 – 2010-09-23 13:51:40

0

这是一种高效,相当短XSLT 1.0解决方案

<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:key name="kFollowing" match="alert" 
    use="generate-id(preceding-sibling::* 
         [ 
         self::proc 
         or 
         self::para 
         ] 
         [1] 
          [self::proc] 
        )"/> 

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

<xsl:template match="proc"> 
    <proc> 
    <xsl:apply-templates select="key('kFollowing', generate-id())" mode="copy"/> 
    </proc> 
</xsl:template> 

<xsl:template match="alert" mode="copy"> 
    <xsl:call-template name="identity"/> 
</xsl:template> 

<xsl:template match="alert[preceding-sibling::* 
       [ 
       self::proc 
       or 
       self::para 
       ] 
       [1] 
        [self::proc] 
       ]" 
           /> 
</xsl:stylesheet> 

当所提供的XML文档被应用这个变换(校正为良好形成):

<body> 
    <proc>Test</proc> 
    <alert>Test1: alert 1</alert> 
    <alert>Test1: alert 2</alert> 
    <para>Test para 1</para> 
    <alert>Test2: alert 1</alert> 
    <alert>Test2: alert 2</alert> 
    <alert>Test2: alert 3</alert> 
    <proc>Test</proc> 
    <alert>Test3: alert 1</alert> 
    <alert>Test3: alert 2</alert> 
    <alert>Test3: alert 3</alert> 
</body> 

有用结果产生

<body> 
    <proc> 
     <alert>Test1: alert 1</alert> 
     <alert>Test1: alert 2</alert> 
    </proc> 
    <para>Test para 1</para> 
    <alert>Test2: alert 1</alert> 
    <alert>Test2: alert 2</alert> 
    <alert>Test2: alert 3</alert> 
    <proc> 
     <alert>Test3: alert 1</alert> 
     <alert>Test3: alert 2</alert> 
     <alert>Test3: alert 3</alert> 
    </proc> 
</body> 

待办事项:使用的键使得该转换比使用preceding-sibling::following-sibling::轴快许多倍(在许多alert兄弟姐妹的情况下)。

+0

+1对于分类解决方案。 – 2010-09-23 13:37:51

0

除了Dimitre的很好的答案(可能是这类问题的CLASIC解决方案),这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()[1]|@*"/> 
     </xsl:copy> 
     <xsl:apply-templates select="following-sibling::node()[1]"/> 
    </xsl:template> 
    <xsl:template match="proc"> 
     <proc> 
      <xsl:apply-templates select="following-sibling::node()[1]" 
           mode="open"/> 
     </proc> 
     <xsl:apply-templates select="following-sibling::node() 
             [not(self::alert)][1]"/> 
    </xsl:template> 
    <xsl:template match="node()" mode="open"/> 
    <xsl:template match="alert" mode="open"> 
     <xsl:copy-of select="."/> 
     <xsl:apply-templates select="following-sibling::node()[1]" 
          mode="open"/> 
    </xsl:template> 
</xsl:stylesheet> 

输出:

<body> 
    <proc> 
     <alert>Test1: alert 1</alert> 
     <alert>Test1: alert 2</alert> 
    </proc> 
    <para>Test para 1</para> 
    <alert>Test2: alert 1</alert> 
    <alert>Test2: alert 2</alert> 
    <alert>Test2: alert 3</alert> 
    <proc> 
     <alert>Test3: alert 1</alert> 
     <alert>Test3: alert 2</alert> 
     <alert>Test3: alert 3</alert> 
    </proc> 
</body> 

注意:本用细粒度trasversal。

编辑:与模式更好的模式匹配。