在不使用for-each的情况下增加xslt 2.0中的变量

时间:2016-04-02 14:49:35

标签: xml xslt

我有一个xml(如下所示),其中如果一个节点(ref_name_1,ref_name_2,ref_name_3)包含一些文本,那么我们将使用xslt生成相应的节点,并在属性中为例如1,2等分配一个id号。我试图找出解决方案,但是没有发现任何与此相关的内容甚至没有在stackoverflow上,所以一点帮助都会非常明显。

示例XML

<?xml version="1.0" encoding="UTF-8"?>
<reference>
   <ref_name_1>reference1</ref_name_1>
   <ref_company_1>company1</ref_company_1>
   <ref_position_1>position3</ref_position_1>
   <ref_name_2 />
   <ref_company_2>company2</ref_company_2>
   <ref_position_2>position2</ref_position_2>
   <ref_name_3>reference3</ref_name_3>
   <ref_company_3>company3</ref_company_3>
   <ref_position_3>position3</ref_position_3>
</reference> 

预期产出:

<?xml version="1.0" encoding="UTF-8"?>
<services>
   <service name="reference" id="1">
      <name>reference1</name>
      <company>company1</company>
      <position>position1</position>
   </service>
   <service name="reference" id="2">
      <name>reference3</name>
      <company>company3</company>
      <position>position3</position>
   </service>
</services>

2 个答案:

答案 0 :(得分:3)

关键是position()功能。它适用于<xsl:for-each>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output indent="yes"/>  

  <xsl:template match="/reference">
    <services>
      <xsl:for-each select="*[starts-with(local-name(), 'ref_name_')][. != '']">
        <xsl:variable name="originalNumber" select="substring-after(local-name(), 'ref_name_')"/>

        <service name="reference" id="{position()}">
          <name>
            <xsl:value-of select="."/>
          </name>
          <company>
            <xsl:value-of select="following-sibling::*[local-name()=concat('ref_company_', $originalNumber)][1]"/>
          </company>
          <position>
            <xsl:value-of select="following-sibling::*[local-name()=concat('ref_position_', $originalNumber)][1]"/>
          </position>
        </service>
      </xsl:for-each>
    </services>
  </xsl:template>

</xsl:stylesheet>

<xsl:apply-tempaltes>一样:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output indent="yes"/>  

  <xsl:template match="/reference">
    <services>
      <xsl:apply-templates select="*[starts-with(local-name(), 'ref_name_')][. != '']"/>
    </services>
  </xsl:template>


  <xsl:template match="*[starts-with(local-name(), 'ref_name_')][. != '']">
    <xsl:variable name="originalNumber" select="substring-after(local-name(), 'ref_name_')"/>

    <service name="reference" id="{position()}">
      <name>
        <xsl:value-of select="."/>
      </name>
      <company>
        <xsl:value-of select="following-sibling::*[local-name()=concat('ref_company_', $originalNumber)][1]"/>
      </company>
      <position>
        <xsl:value-of select="following-sibling::*[local-name()=concat('ref_position_', $originalNumber)][1]"/>
      </position>
    </service>  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

还有xsl:number,此处与for-each-group group-starting-with一起使用:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output indent="yes"/>

    <xsl:template match="reference">
        <services>
            <xsl:for-each-group select="*" group-starting-with="*[starts-with(local-name(), 'ref_name_')]">
                <xsl:if test="normalize-space()">
                    <service name="reference">
                        <xsl:attribute name="id">
                            <xsl:number count="*[starts-with(local-name(), 'ref_name_') and normalize-space()]"/>
                        </xsl:attribute>
                        <xsl:apply-templates select="current-group()"/>
                    </service>
                </xsl:if>
            </xsl:for-each-group>
        </services>
    </xsl:template>

    <xsl:template match="reference/*">
        <xsl:element name="{replace(local-name(), '^ref_|_[0-9]+$', '')}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>

</xsl:transform>

http://xsltransform.net/ncdD7nm在线。