How to get the Particular XML elements indexes with respect to this scenario in xslt 2.0?

我是研究僧i 提交于 2019-12-02 00:05:00

Try this ...

<xsl:stylesheet 
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:user="http://http://stackoverflow.com/questions/11356668"
  exclude-result-prefixes="xs fn w user">

<xsl:output indent="yes"/>

<xsl:function name="user:bookmark-index" as="xs:string">
  <xsl:param name="bookmark-node" as="element()"/>
  <xsl:for-each select="$bookmark-node">
    <xsl:value-of select="count( preceding-sibling::*) -
                          count( preceding-sibling::w:sdt)" />
  </xsl:for-each>
</xsl:function>

<xsl:template match="/">
 <Document>
  <Bookmark indexes="{
    fn:string-join( for $i in w:document/w:body/w:Bookmark return user:bookmark-index( $i), ',')
    }" />
 </Document>
</xsl:template>

</xsl:stylesheet>

... or this equivalent without functions ...

<xsl:stylesheet 
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="xs fn w">

<xsl:output indent="yes"/>

<xsl:template match="/">
 <Document>
  <Bookmark indexes="{
    fn:string-join( for $i in w:document/w:body/w:Bookmark return
            xs:string( count($i/preceding-sibling::*) -
                       count($i/preceding-sibling::w:sdt)),
                  ',')
    }" />
 </Document>
</xsl:template>

</xsl:stylesheet>

This short and simple transformation uses <xsl:number>:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
 exclude-result-prefixes="w xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*[//w:Bookmark]">
     <Document>
       <xsl:variable name="vIndexes" as="xs:string+">
        <xsl:apply-templates/>
       </xsl:variable>
       <Bookmark indexes="{string-join($vIndexes, ',')}"/>
     </Document>
 </xsl:template>

 <xsl:template match="w:Bookmark">
  <xsl:variable name="vPos" as="xs:integer">
    <xsl:number count="/*/w:body/*[not(self::w:sdt)]" level="any"/>
  </xsl:variable>

  <xsl:sequence select="string($vPos -1)"/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
        <w:body>
            <w:sdt>
                <w:sdtContent>
                    <w:p>
                        <w:pPr>
                            <w:pStyle w:val="TOC"></w:pStyle>
                        </w:pPr>
                    </w:p>
                </w:sdtContent>
            </w:sdt>

            <w:p>   <!-- index value 0 -->
            </w:p>

            <w:p>   <!-- index value 1 -->
            </w:p>

            <w:Bookmark></w:Bookmark> <!-- index value 2 -->
            <w:Bookmark></w:Bookmark> <!-- index value 3 -->

            <w:pict></w:pict> <!-- index value 4 -->

            <w:p>     <!-- index value 5 -->
            </w:p>

            <w:Bookmark></w:Bookmark> <!-- index value 6 -->
            <w:Bookmark></w:Bookmark> <!-- index value 7 -->
            <w:p>  <!-- index value 8 -->
            </w:p>

        </w:body>
</w:document>

the wanted, correct result is produced:

<Document>
   <Bookmark indexes="2,3,6,7"/>
</Document>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!