计算忽略空白节点的节点

count the nodes ignoring blank nodes

我有以下 XML.

案例一

<body>
    <nd>
        <pnn>1.1</pnn>
        <h1>PART 54</h1>
        <ti>Construction</ti>
    </nd>
    <nd>
        <h1>PART 54</h1>
        <h2>I INTRODUCT</h2>
        <ti>Time</ti>
    </nd>
    <nd>
        <h1>PART 54</h1>
        <h2>I INTRODUCT</h2>
        <ti>Power</ti>
    </nd>
    <nd>
        <h1>PART 54</h1>
        <h2>II APPLICATIONS</h2>
        <ti>Filing</ti>
    </nd>
</body>

案例二

<body>
    <nd>
        <pnn>1.1</pnn>
        <h1>PART 54</h1>
        <h2>I INTRODUCT</h2>
        <ti>Construction</ti>
    </nd>
    <nd>
        <h1>PART 54</h1>
        <h2>I INTRODUCT</h2>
        <ti>Time</ti>
    </nd>
    <nd>
        <h1>PART 54</h1>
        <h2>II APPLICATIONS</h2>
        <ti>Filing</ti>
    </nd>
</body>

和下面的 XSLT

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:template match="/">
      <hmtl>
        <head>
          <title>New Version!</title>
        </head>
       <xsl:apply-templates select="body"></xsl:apply-templates>
      </hmtl>
    </xsl:template>

    <xsl:template match="body">
         <xsl:for-each select="nd">
            <xsl:apply-templates select = "."/>
        </xsl:for-each>
    </xsl:template>
   <xsl:template match="pnn"/>
   <xsl:template match="h1"/>
   <xsl:template match="h2"/>
   <xsl:template match="ti"/>
<xsl:variable name="FinalChap">
        <xsl:value-of select="substring-before((//pnn)[1],'.')"/>
    </xsl:variable>
    <xsl:variable name="FinalChn">
        <xsl:value-of select="$FinalChap"/>
    </xsl:variable>
    <xsl:variable name="Finalchapternumber">
        <xsl:value-of select="format-number($FinalChn,'00')"/>
    </xsl:variable>

    <xsl:template name="section" match="nd">
        <xsl:variable name="count">
            <xsl:number count="nd" level="any"/>
        </xsl:variable>
        <xsl:variable name="classname">
            <!--Get name attribute of current node -->
            <xsl:value-of select="concat('section-sect','1')"/>
        </xsl:variable>
        <xsl:variable name="classname1">
            <!--Get name attribute of current node -->
            <xsl:value-of select="concat('section-sect','2')"/>
        </xsl:variable>
        <xsl:variable name="classname2">
            <!--Get name attribute of current node -->
            <xsl:value-of select="concat('section-sect','3')"/>
        </xsl:variable>

        <!--Create a string variable by concat string method  -->
        <xsl:variable name="sectionname">
            <xsl:value-of select="concat('CH_',$Finalchapternumber,'-SEC-', $count)"/>
        </xsl:variable>
            <div class="{$classname}">
            <xsl:if test="./h2 and not(preceding::h2[1]/text() = ./h2/text())">
                <a name="{$sectionname}"> </a>
                <div class="section-title">
                    <xsl:if test="not(preceding::h2[1]/text() = ./h2/text())">
                        <xsl:apply-templates select="h2" mode="section"/>
                    </xsl:if>
                </div>
            </xsl:if>
            <xsl:if test="not(lower-case(./ti/text()) = lower-case(./h2/text()))">
                <xsl:if test="./ti">
                    <div class="{$classname2}">
                        <xsl:apply-templates select="ti" mode="section"/>
                    </div>
                </xsl:if>
            </xsl:if>
            <xsl:apply-templates select="child::node()[not(self::h2|self::ti)]"/>
        </div>
    </xsl:template>
    <xsl:template match="ti" mode="section">
        <xsl:apply-templates select="./node()[1][self::page]" mode="first"/>
        <xsl:variable name="sectionnum">
            <xsl:number count="nd" level="any"/>
        </xsl:variable>
        <a name="CH_{$Finalchapternumber}-SEC-{$sectionnum}"/>
        <div class="section-title">
            <xsl:apply-templates/>
        </div>
    </xsl:template>
    <xsl:template match="h2" mode="section">
        <div class="section-title">
            <xsl:apply-templates select="child::node()[not(self::fnt)]"/>
        </div>
    </xsl:template>


</xsl:transform>

我在这里尝试根据条件增加节号。应该进行计数,如果没有节点(这里 h2)应该忽略 <a name="CH_01-SEC-XX"></a> 我可以使用 <xsl:if test="./h2 and not(preceding::h2[1]/text() = ./h2/text())"> 来完成,但我面临的挑战是 count 并没有忽略它。

当前输出。案例一

<div class="section-sect1">
    <a name="CH_01-SEC-1"/>
    <div class="section-title">
        <div class="section-title">I INTRODUCT</div>
    </div>
    <div class="section-sect3">
        <a name="CH_01-SEC-1"/>
        <div class="section-title">Construction</div>
    </div>
</div>
<div class="section-sect1">
    <div class="section-sect3">
        <a name="CH_01-SEC-2"/>
        <div class="section-title">Time</div>
    </div>
</div>
<div class="section-sect1">
    <div class="section-sect3">
        <a name="CH_01-SEC-3"/>
        <div class="section-title">Power</div>
    </div>
</div>
<div class="section-sect1">
    <a name="CH_01-SEC-4"/>
    <div class="section-title">
        <div class="section-title">II APPLICATIONS</div>
    </div>
    <div class="section-sect3">
        <a name="CH_01-SEC-4"/>
        <div class="section-title">Filing</div>
    </div>
</div>

预期输出情况 1

<div class="section-sect1">
    <a name="CH_01-SEC-1"/>
    <div class="section-title">
        <div class="section-title">I INTRODUCT</div>
    </div>
    <div class="section-sect3">
        <a name="CH_01-SEC-2"/>
        <div class="section-title">Construction</div>
    </div>
</div>
<div class="section-sect1">
    <div class="section-sect3">
        <a name="CH_01-SEC-3"/>
        <div class="section-title">Time</div>
    </div>
</div>
<div class="section-sect1">
    <div class="section-sect3">
        <a name="CH_01-SEC-4"/>
        <div class="section-title">Power</div>
    </div>
</div>
<div class="section-sect1">
    <a name="CH_01-SEC-5"/>
    <div class="section-title">
        <div class="section-title">II APPLICATIONS</div>
    </div>
    <div class="section-sect3">
        <a name="CH_01-SEC-6"/>
        <div class="section-title">Filing</div>
    </div>
</div>

当前输出案例 2

<div class="section-sect1"><a name="CH_01-SEC-1"></a><div class="section-title">
         <div class="section-title">I INTRODUCT</div>
      </div>
      <div class="section-sect3"><a name="CH_01-SEC-1"></a><div class="section-title">Construction</div>
      </div>
      </div>
   <div class="section-sect1">
      <div class="section-sect3"><a name="CH_01-SEC-2"></a><div class="section-title">Time</div>
      </div>
   </div>
   <div class="section-sect1"><a name="CH_01-SEC-3"></a><div class="section-title">
         <div class="section-title">II APPLICATIONS</div>
      </div>
      <div class="section-sect3"><a name="CH_01-SEC-3"></a><div class="section-title">Filing</div>
      </div>
   </div>

预期输出情况 2

<div class="section-sect1">
    <a name="CH_01-SEC-1"/>
    <div class="section-title">
        <div class="section-title">I INTRODUCT</div>
    </div>
    <div class="section-sect3">
        <a name="CH_01-SEC-2"/>
        <div class="section-title">Construction</div>
    </div>
</div>
<div class="section-sect1">
    <div class="section-sect3">
        <a name="CH_01-SEC-3"/>
        <div class="section-title">Time</div>
    </div>
</div>
<div class="section-sect1">
    <a name="CH_01-SEC-4"/>
    <div class="section-title">
        <div class="section-title">II APPLICATIONS</div>
    </div>
    <div class="section-sect3">
        <a name="CH_01-SEC-5"/>
        <div class="section-title">Filing</div>
    </div>
</div>

在当前输出中有重复的 CH_01-SEC-1 谁能告诉我如何将它变成一系列 1...n

这是一个有效的 DEmo

谢谢

怎么样....

<xsl:transform
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  version="2.0">
<xsl:output method="html" doctype-public="XSLT-compat" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:variable name="FinalChap">
  <xsl:value-of select="format-number( xs:integer( substring-before((/body/nd/pnn)[1],'.')), '00')"/>
</xsl:variable>

<xsl:template match="/">
  <html>
  <head><title>New Version from Sean!</title></head>
  <xsl:apply-templates />
 </html>
</xsl:template>

<xsl:template match="*">
 <xsl:apply-templates />
</xsl:template>

<xsl:template match="text()|processing-instruction()|comment()|@*" />

<xsl:template match="body">
  <xsl:for-each-group select="nd" group-adjacent="h2/text()">
    <xsl:variable name="group-position" select="position()" />
    <xsl:for-each select="current-group()">
     <xsl:call-template name="nd">
      <xsl:with-param name="group-position" select="$group-position" />
      <xsl:with-param name="is-head" select="position() eq 1" as="xs:boolean" />
     </xsl:call-template>  
    </xsl:for-each>  
  </xsl:for-each-group>
</xsl:template>

<xsl:template name="nd">
 <xsl:param name="group-position" select="1" as="xs:integer" />
 <xsl:param name="is-head" select="true()" as="xs:boolean" />

 <div class="section-sect1">
  <xsl:if test="$is-head"> 
   <xsl:call-template name="a-link">
    <xsl:with-param name="group-position" select="$group-position" />
    <xsl:with-param name="delta" select="0" as="xs:integer" />
   </xsl:call-template>  
   <div class="section-title">
    <div class="section-title"><xsl:value-of select="h2" /></div>
   </div>
   </xsl:if>  
  <div class="section-sect3">
    <xsl:call-template name="a-link">
     <xsl:with-param name="group-position" select="$group-position" />
     <xsl:with-param name="delta" select="1" as="xs:integer" />
    </xsl:call-template>  
    <div class="section-title"><xsl:value-of select="ti" /></div>
  </div>
 </div>
</xsl:template>


<xsl:template name="a-link">
 <xsl:param name="group-position" select="1" as="xs:integer" />
 <xsl:param name="delta" select="0" as="xs:integer" />
  <a name="CH_{$FinalChap}-SEC-{$group-position + count(preceding-sibling::nd) + $delta}" /> 
</xsl:template>  

</xsl:transform>

以上转换,应用于输入文档时...

<body>
    <nd>
        <pnn>1.1</pnn>
        <h1>PART 54</h1>
        <h2>I INTRODUCT</h2>
        <ti>Construction</ti>
    </nd>
    <nd>
        <h1>PART 54</h1>
        <h2>I INTRODUCT</h2>
        <ti>Time</ti>
    </nd>
    <nd>
        <h1>PART 54</h1>
        <h2>I INTRODUCT</h2>
        <ti>Power</ti>
    </nd>
    <nd>
        <h1>PART 54</h1>
        <h2>II APPLICATIONS</h2>
        <ti>Filing</ti>
    </nd>
</body>

... 生成输出文档 ...

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>New Version from Sean!</title>
</head>
<div class="section-sect1">
    <a name="CH_01-SEC-1"/>
    <div class="section-title">
        <div class="section-title">I INTRODUCT</div>
    </div>
    <div class="section-sect3">
        <a name="CH_01-SEC-2"/>
        <div class="section-title">Construction</div>
    </div>
</div>
<div class="section-sect1">
    <div class="section-sect3">
        <a name="CH_01-SEC-3"/>
        <div class="section-title">Time</div>
    </div>
</div>
<div class="section-sect1">
    <div class="section-sect3">
        <a name="CH_01-SEC-4"/>
        <div class="section-title">Power</div>
    </div>
</div>
<div class="section-sect1">
    <a name="CH_01-SEC-5"/>
    <div class="section-title">
        <div class="section-title">II APPLICATIONS</div>
    </div>
    <div class="section-sect3">
        <a name="CH_01-SEC-6"/>
        <div class="section-title">Filing</div>
    </div>
</div>
</html>

说明

body 模板使用 xsl:for-each-group 按公共相邻 h2(h2 标题)对 nd 元素进行分组。 xsl:for-each-group 序列构造函数调用 nd 模板按顺序处理每个 nd 元素,将组号传递给它,以及这个 nd 是组中的第一个('head')。

我从您的示例输出中推断出,每个组的负责人 nd 会产生关于该组的额外内容,包括额外的 a-link。

a-link的个数(例如CH_01-SEC-4中的4个)等于前面的nd的个数加上组号,如果我们不是头nd则再加1 .

替代解决方案

就像给猫剥皮的方法有很多种一样,也有一些同样有效的替代解决方案。您可以使用全推送设计来代替分组。头节点 (<div class="section-title">) 的额外内容可以使用模板模式上的谓词来实现,将这个 h2 与之前的 h2 进行比较。而 a-link 的校正数可以通过 micro-pipelining.

来实现