如何基于position()跳过xslt中的元素

时间:2012-08-20 02:54:29

标签: xslt

这是我的xslt:

这个有效,但仅限于硬编码'1,2,'

<xsl:template match="row[contains('1,2,',concat(position(),','))]" 

工作xslt:

<xsl:stylesheet version="1.0" exclude-result-prefixes="msxsl" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
    <xsl:output method="xml" indent="yes"/>
    <xsl:param name="positions"/>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="row[contains('1,2,',concat(position(),','))]" name="skiprow"/>
</xsl:stylesheet>

但我想将位置值作为参数传递。但它不起作用。 我通过添加一行来检查参数的值,参数很好。

    <xsl:value-of select="$positions"/>
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>

不工作的xslt:

<xsl:stylesheet version="1.0" exclude-result-prefixes="msxsl" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
    <xsl:output method="xml" indent="yes"/>
    <xsl:param name="positions"/>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="row[contains('$positions',concat(position(),','))]" name="skiprow"/>
</xsl:stylesheet>

示例Xml:

<root>
    <row>
        <column1>7004275</column1>
        <column2>NUVCFDK</column2>
    </row>
    <row>
        <column1>1001459</column1>
        <column2>CAN</column2>
        <column3>12</column3>
        <column4>646.80</column4>
        <column5>23-06-2009</column5>
        <column6>31-12-2009</column6>
        <column7/>
    </row>
    <row>
        <column1>1001461</column1>
        <column2>CAN</column2>
        <column3>1</column3>
        <column4>9.50</column4>
        <column5>23-06-2009</column5>
        <column6>31-12-2009</column6>
        <column7/>
    </row>
</root>

1 个答案:

答案 0 :(得分:3)

  

不工作的xslt:

  <xsl:template match="row[contains('$positions',concat(position(),','))]" name="skiprow"/>

在XSLT 1.0中,禁止匹配模式包含变量/参数引用。

改为使用

<xsl:template match="row>
  <xsl:if test=
      "not(contains($vPositions, concat(position(),',')))">
   <xsl:call-template name="identity"/>
  <xsl:if>
</xsl:template>

完成转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="vPositions" select="'1,2,'"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="row">
  <xsl:if test=
   "not(contains($vPositions, concat(position(),',')))">
    <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

并且在提供的XML文档上应用此转换时:

<root>
    <row>
        <column1>7004275</column1>
        <column2>NUVCFDK</column2>
    </row>
    <row>
        <column1>1001459</column1>
        <column2>CAN</column2>
        <column3>12</column3>
        <column4>646.80</column4>
        <column5>23-06-2009</column5>
        <column6>31-12-2009</column6>
        <column7/>
    </row>
    <row>
        <column1>1001461</column1>
        <column2>CAN</column2>
        <column3>1</column3>
        <column4>9.50</column4>
        <column5>23-06-2009</column5>
        <column6>31-12-2009</column6>
        <column7/>
    </row>
</root>

生成了所需的正确结果(第1行和第2行“已删除”):

<root>
   <row>
      <column1>1001461</column1>
      <column2>CAN</column2>
      <column3>1</column3>
      <column4>9.50</column4>
      <column5>23-06-2009</column5>
      <column6>31-12-2009</column6>
      <column7/>
   </row>
</root>

请注意,您的条件不够强 - 参数值"11,13,"将删除四个行 - 1,11 ,3和13。

使用的良好条件是

not(contains($vPositions, concat(',',position(),',')))

这意味着参数必须以逗号字符开头和结尾。

以下是完整的,已更正的转化

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="vPositions" select="',1,2,'"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="row">
  <xsl:if test=
   "not(contains($vPositions, concat(',',position(),',')))">
    <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>