I want to convert one xml to another xml by using XSLT2.0.While doing so, i want to find out some XML elements indexes with respect to my scenaio i explained here...
This is XML Document :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<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>
So, I want to find the <w:Bookmark>
elements indexes.
- If my xml documents contains this elements then i want to create one element named 'Bookmark' and set the attribute 'index'.
- If my xml documents does not contains this elements don't do anything...
The Index Count starts from zero and i need to omit <w:sdt>
elements from calculating index.Please See my comment on the xml document.
My Required output is :
<Document>
<Bookmark indexes="2,3,6,7">
</Bookmark>
</Document>
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>