xslt处理的性能问题

时间:2015-05-29 05:02:13

标签: xslt

我有父子标记结构,需要迭代父标记的子标记,并以新格式设置值。

父标签和子标签都可以重复属性。

我们需要检查子/中是否存在值/标记,然后将其从父标记中取出。

以下是示例xml

<?xml version="1.0" encoding="UTF-8"?>
<item>
  <perishable-indicator >N</perishable-indicator>
  <product-shelf-security-type >ST - SMALL TOY</product-shelf-security-type>
  <before-date>2012-05-30</before-date>
  <partnumber>2</partnumber>
  <season>BASIC SEASON</season>
  <variant>
   <partnumber>4</partnumber>
   <season>BASIC SEASON</season>
   <division-code>055</division-code>
   <department-code>013</department-code>
   <class-code>089</class-code>
  </variant>
</item>

以下是用于迭代父级和子级的示例XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/> 
<xsl:template match="item">
<Product>
    <xsl:variable name="productperishable" select="perishable-indicator"/>
    <xsl:variable name="productsecurity-type" select="product-shelf-security-type"/>
    <xsl:variable name="productbefore-date" select="before-date"/>
    <xsl:variable name="productpartnumber" select="partnumber"/>
    <xsl:variable name="productseason" select="season"/>
<xsl:for-each select="variant">
<sku>
 <xsl:choose>
 <xsl:when test="partnumber">
 <PartNumber><xsl:value-of select="partnumber"/></PartNumber>
 </xsl:when>
 <xsl:when test="$productpartnumber!=''">                       
 <PartNumber><xsl:value-of select="$productpartnumber"/></PartNumber>                       
 </xsl:when>
 </xsl:choose>
<xsl:choose>
 <xsl:when test="perishable-indicator">
 <PartNumber><xsl:value-of select="perishable-indicator"/></PartNumber>
 </xsl:when>
 <xsl:when test="$productperishable!=''">                       
 <Perishable><xsl:value-of select="$productperishable"/></Perishable>                       
 </xsl:when>
 </xsl:choose>
</sku>
</xsl:for-each>
</Product>
</xsl:template>
</xsl:stylesheet>

但是如果我们需要迭代输入xml中存在的几个项目和变体,转换过程需要花费很多时间。任何输入都会有很大的帮助。

1 个答案:

答案 0 :(得分:0)

显示的编码技术将执行很长时间,因为XSLT引擎被迫使用编码循环,而不是使用内置的渲染引擎,并且许多值首先被复制到变量而不是立即复制到输出流。

注意xslt渲染引擎在使用其他编码技术时会自动循环所有元素。将XSLT视为渲染引擎的规范,而不是编程语言。在这种编码技术中,<xsl:apply-templates>(而不是<xsl:for-each&gt;)告诉渲染引擎继续使用它在实际上下文中遇到的任何XML标记。

默认的XSLT模板创建输入的精确副本:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>

    <xsl:template match="/">
       <xsl:apply-templates />
    </xsl:template>

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

</xsl:stylesheet>

如您所见,此样式表中没有<xsl:for-each>命令。您可以使用此规范创建已编译的XSLT渲染,并自行检查运行时的差异。

现在您可以添加转换模板。

如果我正确理解您的规格,您想添加

<xsl:template match="item">
   <Product>
      <xsl:apply-templates select="variant"/>
   </Product>   
</xsl:template>

<xsl:template match="variant">
   <sku>
      <xsl:choose>
         <xsl:when test="partnumber != ''">
            <xsl:apply-templates select="partnumber"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:apply-templates select="../partnumber"/>
         </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
         <xsl:when test="perishable-indicator!= ''">
            <xsl:apply-templates select="perishable-indicator"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:apply-templates select="../perishable-indicator"/>
         </xsl:otherwise>
      </xsl:choose>
   </sku>   
</xsl:template>

这应该涵盖基础知识。使用此规范编译xslt处理器,并告诉我这是否比当前进程更快。

接下来要与输出规范完全兼容,您应该创建另外两个格式化模板来重命名生成的标记:

<xsl:template match="partnumber">
   <PartNumber>
      <xsl:apply-templates/>
   </PartNumber>
</xsl:template>

<xsl:template match="perishable-indicator">
   <Perishable>
      <xsl:apply-templates/>
   </Perishable>
</xsl:template>

这会创建输出

<document>
   <Product>
      <sku>
         <PartNumber>4</PartNumber>
         <Perishable>N</Perishable>
      </sku>
   </Product>
</document>