按属性值对html元素进行分组

时间:2017-03-07 12:41:56

标签: html xml xslt

我需要使用XSLT 2.0将HTML文件转换为XML格式。在这里,我需要将p标签与属性值“ n1 ”,“ n2 ”,“ n3 ”等组合为级别为1的列表, 2级和3级。以下是我的输入

<p class='h1'>the fisr A</p>
<p class='txt'>one</p>
<p class='h2'>the sec sec B</p>
<p class="n1"><span>(a)</span><span>Minimum average</span></p>
<p class="n1"><span>(b)</span><span>Minimum average daily</span></p>
<p class="n1"><span>(c)</span><span>Cooling period.</span></p>
<p class="n1"><span>(d)</span><span>Securities of the company</span></p>
<p class="n2"><span>■</span><span>Th second level list</span><span>.</span></p>
<p class="n2"><span>■</span><span>Th second level list</span></p>
<p class="n3"><span>-</span><span>Th second level list</span><span>.</span></p>
<p class="n3"><span>-</span><span>Th second level list</span></p>
<p class='txt'>the next text</p>
<p class='h3'>the fisr C</p>
<p class='txt'>four</p>
<p class='txt'>five</p>
<p class="n1"><span>(a)</span><span>Minimum average</span></p>
<p class="n1"><span>(b)</span><span>Minimum average daily</span></p>
<p class='h1'>the seccond A</p>

所需的输出

<p class="h1">the fisr A</p>
<p class="txt">one</p>
<p class="h2">the sec sec B</p>
<list1>
    <li>
        <span>(a)</span>
        <span>Minimum average</span>
    </li>
    <li>
        <span>(b)</span>
        <span>Minimum average daily</span>
    </li>
    <li>
        <span>(c)</span>
        <span>Cooling period.</span>
    </li>
    <li>
        <span>(d)</span>
        <span>Securities of the company</span>
        <list2>
            <li>
                <span>?</span>
                <span>Th second level list</span>
                <span>.</span>
            </li>
            <li>
                <span>?</span>
                <span>Th second level list</span>
                <list3>
                    <li>
                        <span>-</span>
                        <span>Th second level list</span>
                        <span>.</span>
                    </li>
                    <li>
                        <span>-</span>
                        <span>Th second level list</span>
                    </li>
                </list3>
            </li>
        </list2>
    </li>
</list1>
<p class="txt">the next text</p>
<p class="h3">the fisr C</p>
<p class="txt">four</p>
<p class="txt">five</p>
<list1>
    <li>
        <span>(a)</span>
        <span>Minimum average</span>
    </li>
    <li>
        <span>(b)</span>
        <span>Minimum average daily</span>
    </li>
</list1>
<p class="h1">the seccond A</p>

我使用下面的代码。但输出错误

   <xsl:template match="*">
  <xsl:for-each-group select="*" group-adjacent="./@class='n1'">
    <list1>
      <xsl:for-each-group select="current-group()" group-adjacent="./@class='n2'">
        <list2>
          <xsl:apply-templates select="current-group()"></xsl:apply-templates>
        </list2>
      </xsl:for-each-group>
    </list1>
  </xsl:for-each-group>
</xsl:template>

`

任何人都可以帮助我使用for-each-group

获得所需的输出

1 个答案:

答案 0 :(得分:0)

您尚未显示任何上下文或解释规则,您似乎希望首先找到pclass的相邻n1, n2, n3元素,然后编写递归分组获取列表嵌套:

<?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:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs math mf" version="2.0">

    <xsl:output indent="yes"/>

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

    <xsl:function name="mf:group" as="element()*">
        <xsl:param name="input" as="element()*"/>
        <xsl:param name="level" as="xs:integer"/>
        <xsl:if test="$input">
            <xsl:element name="list{$level}">
                <xsl:for-each-group select="$input" group-starting-with="p[@class = concat('n', $level)]">
                    <xsl:choose>
                        <xsl:when test="self::p[@class = concat('n', $level)]">
                            <li>
                                <xsl:apply-templates select="node()"/>
                                <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
                            </li>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="current-group()"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>               
            </xsl:element>
        </xsl:if>
    </xsl:function>

    <xsl:template match="root">
        <xsl:copy>
            <xsl:for-each-group select="*" group-adjacent="@class = ('n1', 'n2', 'n3')">
                <xsl:choose>
                    <xsl:when test="current-grouping-key()">
                        <xsl:sequence select="mf:group(current-group(), 1)"/>
                    </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"?>
<root>
    <p class="h1">the fisr A</p>
    <p class="txt">one</p>
    <p class="h2">the sec sec B</p>
    <p class="n1">
        <span>(a)</span>
        <span>Minimum average</span>
    </p>
    <p class="n1">
        <span>(b)</span>
        <span>Minimum average daily</span>
    </p>
    <p class="n1">
        <span>(c)</span>
        <span>Cooling period.</span>
    </p>
    <p class="n1">
        <span>(d)</span>
        <span>Securities of the company</span>
    </p>
    <p class="n2">
        <span>■</span>
        <span>Th second level list</span>
        <span>.</span>
    </p>
    <p class="n2">
        <span>■</span>
        <span>Th second level list</span>
    </p>
    <p class="n3">
        <span>-</span>
        <span>Th second level list</span>
        <span>.</span>
    </p>
    <p class="n3">
        <span>-</span>
        <span>Th second level list</span>
    </p>
    <p class="txt">the next text</p>
    <p class="h3">the fisr C</p>
    <p class="txt">four</p>
    <p class="txt">five</p>
    <p class="n1">
        <span>(a)</span>
        <span>Minimum average</span>
    </p>
    <p class="n1">
        <span>(b)</span>
        <span>Minimum average daily</span>
    </p>
    <p class="h1">the seccond A</p>
</root>

进入

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <p class="h1">the fisr A</p>
   <p class="txt">one</p>
   <p class="h2">the sec sec B</p>
   <list1>
      <li>
               <span>(a)</span>
               <span>Minimum average</span>
         </li>
      <li>
               <span>(b)</span>
               <span>Minimum average daily</span>
         </li>
      <li>
               <span>(c)</span>
               <span>Cooling period.</span>
         </li>
      <li>
               <span>(d)</span>
               <span>Securities of the company</span>
            <list2>
            <li>
                     <span>■</span>
                     <span>Th second level list</span>
                     <span>.</span>
               </li>
            <li>
                     <span>■</span>
                     <span>Th second level list</span>
                  <list3>
                  <li>
                           <span>-</span>
                           <span>Th second level list</span>
                           <span>.</span>
                     </li>
                  <li>
                           <span>-</span>
                           <span>Th second level list</span>
                     </li>
               </list3>
            </li>
         </list2>
      </li>
   </list1>
   <p class="txt">the next text</p>
   <p class="h3">the fisr C</p>
   <p class="txt">four</p>
   <p class="txt">five</p>
   <list1>
      <li>
               <span>(a)</span>
               <span>Minimum average</span>
         </li>
      <li>
               <span>(b)</span>
               <span>Minimum average daily</span>
         </li>
   </list1>
   <p class="h1">the seccond A</p>
</root>