XSLT:合并具有相同属性值的兄弟姐妹的值

时间:2017-07-10 16:02:19

标签: xml xslt xpath

给出如下输入:

<root>
    <childA style="style_1">Some</childA>
    <childA style="style_1">Text</childA>
    <childA style="style_1">Here</childA>
    <childB style="style_2"/>
    <childA style="style_2">Fake</childA>
    <childB style="style_2"/>
    <childA style="style_1">Some</childA>
    <childA style="style_1">Other</childA>
    <childB style="style_2"/>
    <childA style="style_1">Text</childA>
    <parent>            
        <childA style="style_1">More</childA>
        <childA style="style_1">Text</childA>
    </parent>
</root>

如何合并彼此跟随的元素?所以期望的输出是:

<root>
    <childA style="style_1">SomeTextHere</childA>
    <childB style="style_2"/>
    <childA style="style_2">Fake</childA>
    <childB style="style_2"/>
    <childA style="style_1">SomeOther</childA>
    <childB style="style_2"/>
    <childA style="style_1">Text</childA>
    <parent>            
        <childA style="style_1">MoreText</childA>
    </parent>
</root>

我在其中使用了for-each-groupfor-each尝试了不同的技巧,但是当我使用{{{}时,我得到了重复的节点以及两个<childB>节点之间的<childA>被忽略了1}}我在一个节点而不是两个节点中得到group-adjacent="@style"

这是我的尝试:

SomeOtherText

3 个答案:

答案 0 :(得分:3)

怎么样:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

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

<xsl:template match="*[childA]">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="concat(name(), '|', @style)">
            <xsl:choose>
                <xsl:when test="self::childA">
                    <childA style="{@style}">
                        <xsl:value-of select="current-group()" separator=""/>
                    </childA>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

您可以执行此操作(在注释中明确说明),而不依赖于XSLT 2.0或3.0功能,但可能会在性能下降 vs。以后的版本可用。您只需要知道如何编写一个XPath表达式,区分每个组中的第一个<childA>与其余组,或者反之亦然。例如:

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

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="childA">
    <!-- this is the first childA in a group -->
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="." mode = "merge"/>
    </xsl:copy>
  </xsl:template>

  <!-- Matches (only) the second and subsequent members of a childA group: -->
  <xsl:template match="childA[name(preceding-sibling::*[1]) = 'childA' and @style = preceding-sibling::*[1]/@style]"/>

  <!-- merge in this childA's content and that of the remaining group elements -->
  <xsl:template match="childA" mode="merge">
    <xsl:apply-templates select="node()"/> <!-- attributes ignored -->
    <!-- merge the next sibling, too, if it's in the same group: -->
    <xsl:apply-templates select="following-sibling::*[1][name() = 'childA' and @style = preceding-sibling::*[1]/@style]" mode = "merge"/>
  </xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

使用XSLT 3.0(如Saxon 9.8或实际的Altova支持)我想你想要:

> sessionInfo()
R version 3.2.5 (2016-04-14)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: CentOS release 6.9 (Final)

locale:
 [1] LC_CTYPE=en_US.utf8          LC_NUMERIC=C                
 [3] LC_TIME=en_US.utf8           LC_COLLATE=en_US.utf8       
 [5] LC_MONETARY=en_US.utf8       LC_MESSAGES=en_US.utf8      
 [7] LC_PAPER=en_US.utf8          LC_NAME=en_US.utf8          
 [9] LC_ADDRESS=en_US.utf8        LC_TELEPHONE=en_US.utf8     
[11] LC_MEASUREMENT=en_US.utf8    LC_IDENTIFICATION=en_US.utf8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] randomForest_4.6-12 class_7.3-14        xlsx_0.5.7         
 [4] xlsxjars_0.6.1      rJava_0.9-8         MASS_7.3-47        
 [7] TTR_0.23-1          caret_6.0-76        ggplot2_2.2.0      
[10] lattice_0.20-34     devtools_1.13.2    

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.8        nloptr_1.0.4       plyr_1.8.4             iterators_1.0.8   
 [5] tools_3.2.5        xts_0.10-0         digest_0.6.10      lme4_1.1-12       
 [9] memoise_1.0.0      tibble_1.2         nlme_3.1-128       gtable_0.2.0      
[13] mgcv_1.8-16        Matrix_1.2-7.1     foreach_1.4.3      parallel_3.2.5    
[17] SparseM_1.74       withr_1.0.2        stringr_1.1.0      MatrixModels_0.4-1
[21] stats4_3.2.5       grid_3.2.5         nnet_7.3-12        minqa_1.2.4       
[25] reshape2_1.4.2     car_2.1-3          magrittr_1.5       scales_0.4.1      
[29] codetools_0.2-15   ModelMetrics_1.1.0 splines_3.2.5      assertthat_0.1    
[33] pbkrtest_0.4-6     colorspace_1.3-1   quantreg_5.29      stringi_1.1.2     
[37] lazyeval_0.2.0     munsell_0.4.3      zoo_1.7-13