【问题标题】:How to get the Particular XML elements indexes with respect to this scenario in xslt 2.0?如何在 xslt 2.0 中获取与此场景相关的特定 XML 元素索引?
【发布时间】:2012-07-06 06:02:27
【问题描述】:

我想通过使用 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>

所以,我想找到&lt;w:Bookmark&gt; 元素索引。

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

索引计数从零开始,我需要在计算索引时省略 &lt;w:sdt&gt; 元素。请参阅我对 xml 文档的评论。

我需要的输出是:

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

【问题讨论】:

    标签: xml xslt xpath xslt-2.0


    【解决方案1】:

    试试这个...

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

    【讨论】:

    • Sean,很好,但是如果源 XML 文档不包含任何 w:Bookmark 它仍然会产生 &lt;Document&gt; &lt;Bookmark indexes=""/&gt; &lt;/Document&gt; 。 OP 说过“如果我的 xml 文档不包含此元素,则不执行任何操作”
    【解决方案2】:

    这个简短的转换使用&lt;xsl:number&gt;

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      • 2016-02-22
      • 2019-04-25
      • 2015-04-05
      相关资源
      最近更新 更多