【问题标题】:How to handle Nested 'LIST' with 'label' of each 'list-item'如何使用每个“列表项”的“标签”处理嵌套的“列表”
【发布时间】:2021-03-04 11:05:22
【问题描述】:

在下面的示例中,我们尝试使用每个“列表项”的“标签”处理嵌套的“列表”:

标签示例:

style="ListNum1" 然后是 a.,b.,c., ... 等等
style="ListNum2" 然后 (1),(2),(3), ... 等等。
style="ListNum3" 然后是 (a),(b),(c), ... 等等。

谁能帮忙。

输入 XML:

<?xml version="1.0" encoding="UTF-8"?>
<body>
<list-item style="ListNum1"><p content-type="new">Your client may (<styled-content style="stat" style-type="Stat-Cal">Prob C &#x00a7;13659</styled-content>) because:</p></list-item>
<list-item style="ListNum2"><p content-type="new">For later income tax purposes</p></list-item>
<list-item style="ListNum3"><p content-type="new">Documents a &#x201c;stepped-up basis&#x201d; (<italic>i.e.,</italic> fair.</p></list-item>
<list-item style="ListNum3"><p content-type="new">Provides evidence for your client.</p></list-item>
<list-item style="ListNum2"><p content-type="new">If you or your <bold>client</bold>.</p></list-item>
<list-item style="ListNum1"><p content-type="new">If transfer <italic>unincorporated business</italic> appraisal. <styled-content style="stat" style-type="Stat-Cal">Prob C &#x00a7;13658</styled-content>.</p></list-item>
</body>

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<body>
<list type="ListNum1">
<list-item style="ListNum1"><label>a.</label><p content-type="new">Your client may (<styled-content style="stat" style-type="Stat-Cal">Prob C &#x00a7;13659</styled-content>) because:</p></list-item>
<list type="ListNum2">
<list-item style="ListNum2"><label>(1)</label><p content-type="new">For later income tax purposes</p>
<list type="ListNum3">
<list-item style="ListNum3"><label>(a)</label><p content-type="new">Documents a &#x201c;stepped-up basis&#x201d; (<italic>i.e.,</italic> fair.</p></list-item>
<list-item style="ListNum3"><label>(b)</label><p content-type="new">Provides evidence for your client.</p></list-item>
</list></list-item>
<list-item style="ListNum2"><label>(2)</label><p content-type="new">If you or your <bold>client</bold>.</p></list-item>
</list></list-item>
<list-item style="ListNum1"><label>b.</label><p content-type="new">If transfer <italic>unincorporated business</italic> appraisal. <styled-content style="stat" style-type="Stat-Cal">Prob C &#x00a7;13658</styled-content>.</p></list-item>
</list>
</body>

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:output indent="yes"/>

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

<xsl:template match="list-item[@style='ListNum1']">
    <xsl:if test="not(preceding-sibling::*[1][self::list-item[@style='ListNum1']])">
        <xsl:text disable-output-escaping="yes"><![CDATA[<list list-type="ListNum1">]]></xsl:text>
    </xsl:if>
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:copy>
    <xsl:if test="not(following-sibling::*[1][self::list-item[@style='ListNum1']])">
        <xsl:text disable-output-escaping="yes"><![CDATA[</list>]]></xsl:text>
    </xsl:if>
</xsl:template>

<xsl:template match="list-item[@style='ListNum2']">
    <xsl:if test="not(preceding-sibling::*[1][self::list-item[@style='ListNum2']])">
        <xsl:text disable-output-escaping="yes"><![CDATA[<list list-type="ListNum2">]]></xsl:text>
    </xsl:if>
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:copy>
    <xsl:if test="not(following-sibling::*[1][self::list-item[@style='ListNum2']])">
        <xsl:text disable-output-escaping="yes"><![CDATA[</list>]]></xsl:text>
    </xsl:if>
</xsl:template>

<xsl:template match="list-item[@style='ListNum3']">
    <xsl:if test="not(preceding-sibling::*[1][self::list-item[@style='ListNum3']])">
        <xsl:text disable-output-escaping="yes"><![CDATA[<list list-type="ListNum3">]]></xsl:text>
    </xsl:if>
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:copy>
    <xsl:if test="not(following-sibling::*[1][self::list-item[@style='ListNum3']])">
        <xsl:text disable-output-escaping="yes"><![CDATA[</list>]]></xsl:text>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

参考网址# https://xsltfiddle.liberty-development.net/93nwMoZ/1

【问题讨论】:

  • 使用for-each-group group-starting-with="list-item[@style = 'ListNum' + $level]" 使用递归函数,其中level 是函数的整数参数。
  • @Martin Honnen - 谢谢,但这里的级别不同,我无法联系到。

标签: xslt xslt-1.0 xquery xslt-2.0 xslt-3.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"
    xmlns:mf="http://example.com/mf"
    expand-text="yes"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="format-map" as="map(xs:integer, xs:string)"
    select="map { 1 : 'a', 2 : '1', 3 : 'A' }"/>
    
  <xsl:function name="mf:group" as="node()*">
      <xsl:param name="items" as="element(list-item)*"/>
      <xsl:param name="level" as="xs:integer"/>
      <xsl:where-populated>
          <list type="ListNum{$level}">
            <xsl:for-each-group select="$items" group-starting-with="list-item[@style = 'ListNum' || $level]">
                <xsl:copy>
                    <label>{format-integer(position(), $format-map($level))}</label>
                    <xsl:apply-templates select="node(), mf:group(tail(current-group()), $level + 1)"/>
                </xsl:copy>  
            </xsl:for-each-group>  
          </list>
      </xsl:where-populated>
  </xsl:function>

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="body">
      <xsl:copy>
          <xsl:sequence select="mf:group(list-item, 1)"/>
      </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

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

对于标签格式的详细信息,也许将其扩展为

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    expand-text="yes"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="format-map" as="map(xs:integer, xs:string)"
    select="map { 1 : 'a', 2 : '1', 3 : 'a' }"/>
    
  <xsl:function name="mf:format" as="xs:string">
      <xsl:param name="number" as="xs:integer"/>
      <xsl:param name="level" as="xs:integer"/>
      <xsl:variable name="formatted-number"
        select="format-integer($number, $format-map($level))"/>
      <xsl:sequence
        select="if ($level = 1)
                then  $formatted-number || '.'
                else  '(' || $formatted-number || ')'"/>
  </xsl:function>
    
  <xsl:function name="mf:group" as="node()*">
      <xsl:param name="items" as="element(list-item)*"/>
      <xsl:param name="level" as="xs:integer"/>
      <xsl:where-populated>
          <list type="ListNum{$level}">
            <xsl:for-each-group select="$items" group-starting-with="list-item[@style = 'ListNum' || $level]">
                <xsl:copy>
                    <label>{mf:format(position(), $level)}</label>
                    <xsl:apply-templates select="node(), mf:group(tail(current-group()), $level + 1)"/>
                </xsl:copy>  
            </xsl:for-each-group>  
          </list>
      </xsl:where-populated>
  </xsl:function>

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="body">
      <xsl:copy>
          <xsl:sequence select="mf:group(list-item, 1)"/>
      </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/ei5R4v4/1

【讨论】:

  • 谢谢 Martin,它也可以在 '' 元素之后或 '' 元素之前的其他元素。连同列表
  • @Umaima,好吧,不要在对答案的评论中使要求复杂化。如果您有更复杂的 XML 输入结构并且无法改进建议的代码来处理它们,那么请考虑提出一个新问题,您可以更准确地描述您可以拥有的输入结构以及如何将它们映射到相应的输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-21
  • 1970-01-01
相关资源
最近更新 更多