如何合并两个或多个连续的“样式内容”元素并将其转换为单个while属性相同?

时间:2020-09-06 05:22:03

标签: xml xpath xslt-2.0

有多个具有不同属性@style和@ style-type值的“样式内容”,在这里我们尝试仅合并属性值匹配的连续“样式内容”元素。下面是示例案例:

注意:元素“样式内容”可以具有其他元素,例如“斜体”和“粗体”。这些元素也应保留。此外,“样式内容”元素可以是除“ p”以外的其他父元素。

输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<p content-type="new">For these purposes, the degree of relationship is determined as of the date of execution because of divorce. See <styled-content style="case" style-type="Case-Cal"><italic>Estate of Lira</italic></styled-content><styled-content style="case" style-type="Case-Cal"> (2012) 212 CA4th 1368</styled-content>.</p>
<p content-type="new">Under the <styled-content style="act" style-type="Act-Cal">Trust Law</styled-content>, you owe a duty (see <styled-content style="stat" style-type="Stat-Cal">Probate Code </styled-content><styled-content style="stat" style-type="Stat-Cal">&#x00a7;16061.5</styled-content>). We will discuss with you what specific actions you and we will take to fulfill these duties.</p>
<p content-type="new">Assets may be valued for federal estate tax purposes as of the alternate valuation date <styled-content style="case" style-type="Case-Federal"><italic>Estate of Edward H. Eddy</italic></styled-content><styled-content style="case" style-type="Case-Federal"> (2000) 115 TC </styled-content><styled-content style="case" style-type="Case-Federal">135</styled-content>. The IRS may grant an extension to make the election within the 1-year period even after a timely estate tax return has been filed.</p>
<p content-type="new">Prop Treas Reg see <styled-content style="pub" style-type="Ref-external-CEB"><italic>IRS Issues Temporary and Proposed Basis Consistency and Reporting Regulations,</italic></styled-content><styled-content style="pub" style-type="Ref-external-CEB"> 37 CEB Est Plan Rep 140 (Apr. 2016)</styled-content>.</p>
</root>

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<p content-type="new">For these purposes, the degree of relationship is determined as of the date of execution because of divorce. See <styled-content style="case" style-type="Case-Cal"><italic>Estate of Lira</italic> (2012) 212 CA4th 1368</styled-content>.</p>
<p content-type="new">Under the <styled-content style="act" style-type="Act-Cal">Trust Law</styled-content>, you owe a duty (see <styled-content style="stat" style-type="Stat-Cal">Probate Code &#x00a7;16061.5</styled-content>). We will discuss with you what specific actions you and we will take to fulfill these duties.</p>
<p content-type="new">Assets may be valued for federal estate tax purposes as of the alternate valuation date <styled-content style="case" style-type="Case-Federal"><italic>Estate of Edward H. Eddy</italic> (2000) 115 TC 135</styled-content>. The IRS may grant an extension to make the election within the 1-year period even after a timely estate tax return has been filed.</p>
<p content-type="new">Prop Treas Reg see <styled-content style="pub" style-type="Ref-external-CEB"><italic>IRS Issues Temporary and Proposed Basis Consistency and Reporting Regulations,</italic> 37 CEB Est Plan Rep 140 (Apr. 2016)</styled-content>.</p>
</root>

XSLT代码:

<?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="styled-content[@style[.='case'] and @style-type[.='Case-Cal']]">
    <styled-content>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates/>
        <xsl:if test="following-sibling::node()[1][self::styled-content[@style[.='case'] and @style-type[.='Case-Cal']]]">
            <xsl:apply-templates select="following-sibling::node()[1][self::styled-content[@style[.='case'] and @style-type[.='Case-Cal']]]/node()"/>
        </xsl:if>
    </styled-content>
</xsl:template>
<xsl:template match="styled-content[@style='case' and @style-type[.='Case-Cal']][preceding-sibling::node()[1][self::styled-content[@style='case' and @style-type[.='Case-Cal']]]]"/>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:0)

这似乎是for-each-group group-adjacent的任务,在XSLT 3(自2017年开始提供)中,由于XSLT 3允许使用复合分组密钥,因此表达起来比XSLT 2容易一些。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="*[styled-content]">
      <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:for-each-group 
              select="node()" 
              group-adjacent=". is element(styled-content), @style, @style-type" 
              composite="yes">
              <xsl:choose>
                  <xsl:when test="current-grouping-key()[1]">
                      <xsl:copy>
                          <xsl:apply-templates select="@*, current-group()/node()"/>
                      </xsl:copy>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:apply-templates select="current-group()"/>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bEzkTd6

如果确实需要使用XSLT 2,则需要删除composite="yes",将group-adjacent=". is element(styled-content), @style, @style-type"更改为group-adjacent="string-join((. is element(styled-content), @style, @style-type), '|')",将<xsl:when test="current-grouping-key()[1]">更改为<xsl:when test=". is element(styled-content)">