XSLT - 分组和丢失父文本

时间:2016-07-13 13:54:25

标签: xml grouping xslt-2.0

我遇到了一个问题,当我尝试将代码行分组为块时,我父母的文本丢失了,我不知道为什么。

XML

<body>
  <ul>
    <li>before
      <filepath>one test</filepath> now some code:
      <codeblock>1</codeblock>
      <codeblock>2</codeblock>
      after text</li>
  </ul>
  <section>
    <title>Test2</title>
    <p>qqqq</p>
    <codeblock>1</codeblock>
    <codeblock>2</codeblock>
    <codeblock>3</codeblock>
  </section>
</body>

XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xsl:template match="@*|node()">
    <xsl:choose>
        <xsl:when test="./codeblock[1] or ./msgblock[1]">
            <xsl:call-template name="merge-codeblock">
                <xsl:with-param name="container" select="."/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy>
                <xsl:apply-templates select="@* | node()" />
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="merge-codeblock">
    <xsl:param name="container"/>    
            <xsl:copy>
                <xsl:for-each-group select="*" group-adjacent="boolean(self::codeblock or self::msgblock)">
                    <xsl:choose>
                        <xsl:when test="current-grouping-key() and count(current-group()) gt 1">
                            <xsl:element name="{name()}">
                                <xsl:variable name="name" select="current-group()/node()" />
                                <xsl:for-each select="current-group()/node()">
                                    <xsl:variable name="namee" select="current()" />
                                    <xsl:apply-templates select="current()" />
                                    <xsl:text>&#10;</xsl:text>
                                </xsl:for-each>
                            </xsl:element>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="current-group()" />
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>
            </xsl:copy>        
</xsl:template>

</xsl:stylesheet>

当前结果

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "dtd/task.dtd"><!--<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "dtd/task.dtd">--><body>
   <ul>
      <li><!-- not ok! I lost my li/text() -->
         <filepath>one test</filepath>
         <codeblock>1
2
</codeblock>
      </li>
   </ul>
   <section>
      <title>Test</title>
      <p>fddsfsd</p>
      <codeblock>fdsfds</codeblock>
   </section>
   <section>
      <title>Test2</title>
      <p>qqqq</p>
      <codeblock>1
2
3
</codeblock>
   </section>
</body>

我已尝试将|text()添加到我的群组选择器中,以解决问题,但我的codeblock元素不再合并。

我做错了什么?

编辑: Martin的回答修复了LI的问题,但遗憾的是我现在在我的代码块行之前有一些额外的空格,并且在第一个代码块之后有一个回车符:

<codeblock>
      1
      2
      3
</codeblock>

而不是:

<codeblock>1
2
3</codeblock>

我怎样摆脱这些,我试图删除current-group()中的空格而没有成功。

建议的编辑给了我:

  <codeblock>

1


2


3

   </codeblock>

但问题仍然是奇怪的白色空间。 current-group()包含" ", <codeblock>, " ", <codeblock>, " ", <codeblock>, " ",并在空格中包含回车符。

1 个答案:

答案 0 :(得分:1)

我认为

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

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

    <xsl:template match="*[codeblock | msgblock]">
        <xsl:copy>
            <xsl:for-each-group select="node()"
                group-adjacent="boolean(self::text()[not(normalize-space())] | self::codeblock | self::msgblock)">
                <xsl:choose>
                    <xsl:when test="current-grouping-key() and current-group()[self::*]">
                        <xsl:element name="{name(current-group()[self::*[1]][1])}">
                            <xsl:apply-templates select="current-group()"/>
                        </xsl:element>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="codeblock | msgblock">
        <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>

分组并保留文本,您可能需要调整输出分组内容的部分,因为我不确定您想要的确切结果。

至于你的空白问题,假设你只是在那些codeblockmsgblock元素中有纯文本,那么你可以简化

                <xsl:choose>
                    <xsl:when test="current-grouping-key() and current-group()[self::*]">
                        <xsl:element name="{name(current-group()[self::*[1]][1])}">
                            <xsl:apply-templates select="current-group()"/>
                        </xsl:element>
                    </xsl:when>

                <xsl:choose>
                    <xsl:when test="current-grouping-key() and current-group()[self::*]">
                        <xsl:element name="{name(current-group()[self::*[1]][1])}">
                            <xsl:value-of select="current-group()[self::*]" separator="&#10;"/>
                        </xsl:element>
                    </xsl:when>