2

我想通过使用 XSLT2.0 将一个 xml 转换为另一个 xml。在这样做的同时,我想找出一些关于我在此处解释的场景的 XML 元素索引...

这是 XML 文档:

<?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>

所以,我想找到<w:Bookmark>元素索引。

  1. 如果我的 xml 文档包含这些元素,那么我想创建一个名为“书签”的元素并设置属性“索引”。
  2. 如果我的 xml 文档不包含此元素,则不执行任何操作...

索引计数从零开始,我需要<w:sdt>从计算索引中省略元素。请参阅我对 xml 文档的评论。

我需要的输出是:

  <Document>
    <Bookmark indexes="2,3,6,7">
    </Bookmark>
    </Document>
4

2 回答 2

3

尝试这个 ...

<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>

...或没有功能的等价物...

<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>
于 2012-07-06T07:13:00.567 回答
3

这个简短而简单的转换使用<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>

应用于提供的 XML 文档时:

<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>

产生了想要的正确结果:

<Document>
   <Bookmark indexes="2,3,6,7"/>
</Document>
于 2012-07-06T13:40:31.043 回答