代码之家  ›  专栏  ›  技术社区  ›  Daniel Haley

通过XSLT中的文本处理创建新元素

  •  1
  • Daniel Haley  · 技术社区  · 15 年前

    我想知道是否/如何在XSLT中完成以下任务。如果没有,你会用什么?(我使用了OmniMark,但我想知道在XSLT中是否可以这样做。)

    下面是输入XML的一个示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <fragment>
        <firstElem>
            <secondElem>D12</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J7-10</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>C2-4</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP20-25</secondElem>
        </firstElem>
    </fragment>
    

    我需要做的是把 secondElem 元素并创建尽可能多的新元素 firstElem 必要的元件。“-”是“直通”,因此“A3J7-10”实际上是“A3J7”到“A3J10”(A3J7、A3J8、A3J9、A3J10)。(有时“通”相当大,如A1B2C1-150(A1B2C1至A1B2C150)。

    如果没有破折号,什么都不需要做。

    下面是输出XML的示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <fragment>
        <firstElem>
            <secondElem>D12</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J7</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J8</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J9</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J10</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>C2</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>C3</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>C4</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP20</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP21</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP22</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP23</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP24</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP25</secondElem>
        </firstElem>
    </fragment>
    

    有没有在XSLT中这样做的方法?

    谢谢!

    2 回复  |  直到 15 年前
        1
  •  1
  •   Dimitre Novatchev    15 年前

    这里有一个XSLT2.0解决方案 :

    <xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="node()|@*">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>
    
     <xsl:template match="firstElem[contains(secondElem, '-')]">
       <xsl:analyze-string select="secondElem"
        regex="(^.*[^\d])([\d]*)-([\d]*)">
    
         <xsl:matching-substring>
            <xsl:variable name="vbaseName" select="regex-group(1)"/>
            <xsl:variable name="vstart" select="regex-group(2)"/>
            <xsl:variable name="vend" select="regex-group(3)"/>
    
            <xsl:for-each select=
              "xs:integer($vstart) to xs:integer($vend)">
                    <firstElem>
                        <secondElem>
                          <xsl:value-of select="concat($vbaseName, .)"/>
                        </secondElem>
                    </firstElem>
            </xsl:for-each>
         </xsl:matching-substring>
       </xsl:analyze-string>
     </xsl:template>
    </xsl:stylesheet>
    

    当上述转换应用于所提供的XML文档时 :

    <fragment>
        <firstElem>
            <secondElem>D12</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J7-10</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>C2-4</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP20-25</secondElem>
        </firstElem>
    </fragment>
    

    产生了想要的、正确的结果 :

    <fragment>
        <firstElem>
            <secondElem>D12</secondElem>
        </firstElem>
        <firstElem>
          <secondElem>A3J7</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>A3J8</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>A3J9</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>A3J10</secondElem>
       </firstElem>
        <firstElem>
          <secondElem>C2</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>C3</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>C4</secondElem>
       </firstElem>
        <firstElem>
          <secondElem>QW9R7NP20</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>QW9R7NP21</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>QW9R7NP22</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>QW9R7NP23</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>QW9R7NP24</secondElem>
       </firstElem>
       <firstElem>
          <secondElem>QW9R7NP25</secondElem>
       </firstElem>
    </fragment>
    

    做笔记 :

    1. 正则表达式的使用。

    2. 子表达式捕获和 regex-group() 功能。

    3. 使用 <xsl:analyze-string> <xsl:matching-substring> .

    4. 使用的 to 创建要在其中使用的序列的运算符 <xsl:for-each>

    5. 使用 <xsl:每个> 在非节点(整数)序列上。

        2
  •  2
  •   user357812    15 年前

    此样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="firstElem[contains(.,'-')]" name="firstElem">
            <xsl:param name="from">
                <xsl:call-template name="getfrom"/>
            </xsl:param>
            <xsl:param name="base" select="normalize-space(substring-before(.,concat($from,'-')))"/>
            <xsl:param name="to" select="substring-after(.,'-')"/>
            <xsl:if test="$to >= $from">
                <firstElem>
                    <secondElem>
                        <xsl:value-of select="concat($base,$from)"/>
                    </secondElem>
                </firstElem>
                <xsl:call-template name="firstElem">
                    <xsl:with-param name="from" select="$from + 1"/>
                    <xsl:with-param name="base" select="$base"/>
                    <xsl:with-param name="to" select="$to"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:template>
        <xsl:template name="getfrom">
            <xsl:param name="string" select="substring-before(.,'-')"/>
            <xsl:variable name="last" select="substring($string,string-length($string))"/>
            <xsl:if test="contains('0123456789',$last)">
                <xsl:call-template name="getfrom">
                    <xsl:with-param name="string" select="substring($string,1,string-length($string)-1)"/>
                </xsl:call-template>
                <xsl:value-of select="$last"/>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>
    

    输出:

    <fragment>
        <firstElem>
            <secondElem>D12</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J7</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J8</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J9</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>A3J10</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>C2</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>C3</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>C4</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP20</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP21</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP22</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP23</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP24</secondElem>
        </firstElem>
        <firstElem>
            <secondElem>QW9R7NP25</secondElem>
        </firstElem>
    </fragment>