简体   繁体   English

XSLT显示序列号

[英]XSLT Display Serial number

My input XML consists of the following, 我的输入XML包含以下内容,

<root>
    <entry>
        <type>U</type>
        <value>111</value>
    </entry>
    <entry>
        <type>X</type>
        <value>222</value>
    </entry>
    <entry>
        <type>E</type>
        <value>333</value>
    </entry>
    <entry>
        <type>Q</type>
        <value>444</value>
    </entry>
</root>

Output i required, <ROOT> <ENTRY> <SLNO>1</SLNO> <VALUE>111</VALUE> </ENTRY> <ENTRY> <VALUE>222</VALUE> </ENTRY> <ENTRY> <VALUE>333</VALUE> </ENTRY> <ENTRY> <SLNO>2</SLNO> <VALUE>444</VALUE> </ENTRY> </ROOT> 我需要输出<ROOT> <ENTRY> <SLNO>1</SLNO> <VALUE>111</VALUE> </ENTRY> <ENTRY> <VALUE>222</VALUE> </ENTRY> <ENTRY> <VALUE>333</VALUE> </ENTRY> <ENTRY> <SLNO>2</SLNO> <VALUE>444</VALUE> </ENTRY> </ROOT>

I need to parse all the records, but need to put serial number for records whose type is not X and E. 我需要解析所有记录,但是需要为类型不是X和E的记录添加序列号。

I have written a for-each to for the same and used ´position()´ to display a serial number with condtion for type E and X. So I'm getting serial number as 1, 4 instead of 1, 2 because of ´postion()´. 我用相同的for-each编写了一个,并使用“ position()”来显示带有类型E和X的序列号。因此,由于“ postion()´。

I thought of creating a global variable and increment it inside my if block, but XSLT 1.0 will not allow to increment variable values. 我曾想创建一个全局变量并将其在我的if块内递增,但是XSLT 1.0将不允许递增变量值。

How can I achieve this? 我该如何实现?

My sample XSL code is asl follows, 我的示例XSL代码如下:

<xsl:for-each select="/ROOT/ENTRY">
    <xsl:if test="(TYPE != 'X') and (TYPE != 'E')">             
        <xsl:text><![CDATA[<SLNO>]]></xsl:text>
        <xsl:number value="position()"/>
        <xsl:text><![CDATA[</SLNO>]]></xsl:text>
    </xsl:if>
    <!-- Printing remaining values -->
</xsl:for-each>

Please help. 请帮忙。

Instead of using position(), you could count the number of preceding type elements in your XML 除了使用position()之外,您还可以计算XML中先前类型元素的数量

<xsl:value-of select="count(preceding::type[. != 'X' and . != 'E']) + 1" />

Additionally, you can simplify your current XSLT by matching the type element directly, rather than the entry element, and then just replace it with the new slno element. 另外,您可以通过直接匹配type元素(而不是entry元素)来简化当前的XSLT,然后将其替换为新的slno元素。

<xsl:template match="type[. != 'X' and . != 'E']">

For example, try the following XSLT 例如,尝试以下XSLT

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

   <xsl:template match="type[. != 'X' and . != 'E']">
      <slno><xsl:value-of select="count(preceding::type[. != 'X' and . != 'E']) + 1" /></slno>
   </xsl:template>

   <xsl:template match="type" />

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

When applied to your sample XML, the following is output 当应用于示例XML时,输出以下内容

<root>
   <entry>
      <slno>1</slno>
      <value>111</value>
   </entry>
   <entry>
      <value>222</value>
   </entry>
   <entry>
      <value>333</value>
   </entry>
   <entry>
      <slno>2</slno>
      <value>444</value>
   </entry>
</root>

Note, I am using all lower-case element names here. 注意,我在这里使用所有小写的元素名称。 I wasn't sure from your question if you wanted to translate them into upper-case or not. 从您的问题中我不确定您是否要将它们翻译成大写。

The accepted answer is a good one, except that the implemented algorithm has O(N^2) (quadratic) time complexity and executes very slow on large inputs . 可接受的答案是一个很好的答案,除了所实现的算法具有O(N ^ 2)(二次)时间复杂度并且在大输入量时执行速度非常慢

Here is transformation with linear-time-complexity O(N): 这是线性时间复杂度为O(N)的变换:

<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:template match="node()|@*">
  <xsl:param name="pCount" select="0"/>
  <xsl:copy>
   <xsl:apply-templates select="node()[1]|@*">
     <xsl:with-param name="pCount" select="$pCount"/>
   </xsl:apply-templates>
  </xsl:copy>
  <xsl:apply-templates select="following-sibling::node()[1]">
     <xsl:with-param name="pCount" select="$pCount"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="entry[not(contains('EX', type))]">
  <xsl:param name="pCount" select="0"/>

  <xsl:copy>
   <slno><xsl:value-of select="$pCount+1"/></slno>
   <xsl:apply-templates select="node()[1]|@*">
     <xsl:with-param name="pCount" select="$pCount+1"/>
   </xsl:apply-templates>
  </xsl:copy>
  <xsl:apply-templates select="following-sibling::node()[1]">
     <xsl:with-param name="pCount" select="$pCount+1"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="type">
   <xsl:param name="pCount" select="0"/>
   <xsl:apply-templates select="following-sibling::node()[1]">
     <xsl:with-param name="pCount" select="$pCount+1"/>
   </xsl:apply-templates>
 </xsl:template>
</xsl:stylesheet>

When applied on the provided XML document: 当应用于提供的XML文档时:

<root>
    <entry>
        <type>U</type>
        <value>111</value>
    </entry>
    <entry>
        <type>X</type>
        <value>222</value>
    </entry>
    <entry>
        <type>E</type>
        <value>333</value>
    </entry>
    <entry>
        <type>Q</type>
        <value>444</value>
    </entry>
</root>

the wanted, correct result is produced: 所需的正确结果产生了:

<root>
   <entry>
      <slno>1</slno>
      <value>111</value>
   </entry>
   <entry>
      <value>222</value>
   </entry>
   <entry>
      <value>333</value>
   </entry>
   <entry>
      <slno>2</slno>
      <value>444</value>
   </entry>
</root>

Explanation : 说明

  1. Using and overriding the "fine-grained identity rule" . 使用并覆盖“细粒度身份规则” It bears its name due to the fact that templates are applied only to one node (in document order) at a time. 它之所以得名,是因为模板一次仅按一个文档应用于一个节点。

  2. The "fine-grained identity rule" is modified to contain and pass a parameter $pCount , which contains the maximum current "serial number" reached so far. 修改了“细粒度身份规则”以包含并传递参数$pCount ,该参数包含到目前为止已达到的最大当前“序列号”。

  3. This works without the need to return back the current serial number, because all entry elements are siblings. 由于所有entry元素都是同级元素,因此无需返回当前序列号即可正常工作。

  4. The time complexity is linear, because there is no counting of all preceding siblings at every node, as done in the other answer. 时间复杂度是线性的,因为没有像其他答案那样对每个节点上的所有先前同级进行计数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM