1

我需要根据属性增加 xslt 中的值。假设我的xml是这样的,

   <comp>
   <fig xml:id="c1-fig-001"/>
   <fig xml:id="c1-fig-002"/>
   <fig xml:id="c1-fig-003"/>
   <fig xml:id="c1-fig-004" resumeatnum="7"/>
   <fig xml:id="c1-fig-005"/>
   <fig xml:id="c1-fig-006"/>
   <fig xml:id="c1-fig-007" resumeatnum="18"/>
   <fig xml:id="c1-fig-008"/>
   <fig xml:id="c1-fig-009"/>
   </comp>

我需要这样的输出,

<comp>
<fig xml:id="c1-fig-001"/>
<fignum>1.1</fignum>
<fig xml:id="c1-fig-002"/>
<fignum>1.2</fignum>
<fig xml:id="c1-fig-003"/>
<fignum>1.3</fignum>
<fig xml:id="c1-fig-004" resumeatnum="7"/>
<fignum>1.7</fignum>
<fig xml:id="c1-fig-005"/>
<fignum>1.8</fignum>
<fig xml:id="c1-fig-006"/>
<fignum>1.9</fignum>
<fig xml:id="c1-fig-007" resumeatnum="18"/>
<fignum>1.18</fignum>
<fig xml:id="c1-fig-008"/>
<fignum>1.19</fignum>
<fig xml:id="c1-fig-009"/>
<fignum>1.20</fignum>
</comp>

我需要从xml:id1from这样的属性中获取值,c1然后从后面的数字中获取另一个数字fig

如果有一个属性resumeatnum,那么我需要使用该值而不是正常值并增加下一个节点的值。请提供 xslt 来执行此操作。

4

5 回答 5

1

以下 XSLT 2.0 样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  exclude-result-prefixes="xs" 
  version="2.0">

  <xsl:template match="comp">
    <xsl:for-each-group select="fig" group-starting-with="*[@resumeatnum]">
      <xsl:variable name="base" select="(@resumeatnum, 1)[1] - 1"/>
      <xsl:for-each select="current-group()">
        <xsl:copy-of select="."/>
        <fignum>1.<xsl:value-of select="position()+$base"/></fignum>
      </xsl:for-each>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

产生以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<fig xml:id="c1-fig-001"/>
<fignum>1.1</fignum>
<fig xml:id="c1-fig-002"/>
<fignum>1.2</fignum>
<fig xml:id="c1-fig-003"/>
<fignum>1.3</fignum>
<fig xml:id="c1-fig-004" resumeatnum="7"/>
<fignum>1.7</fignum>
<fig xml:id="c1-fig-005"/>
<fignum>1.8</fignum>
<fig xml:id="c1-fig-006"/>
<fignum>1.9</fignum>
<fig xml:id="c1-fig-007" resumeatnum="18"/>
<fignum>1.18</fignum>
<fig xml:id="c1-fig-008"/>
<fignum>1.19</fignum>
<fig xml:id="c1-fig-009"/>
<fignum>1.20</fignum>
于 2012-07-26T22:35:19.747 回答
1

这是一个更短(33 个格式良好的短行)和更简单的 XSLT 1.0 解决方案(三个短模板, no substring()​​, no substring-before()​​,no complex and long ,多行表达式, no concat()​​, no xsl:for-each​​, no xsl:if​​, no xsl:variable​​, no string-length()​​, noxsl:call-template ​​:

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

 <xsl:key name="kFollowing" match="fig[not(@resumeatnum)]"
      use="generate-id((preceding-sibling::*[@resumeatnum][1]
                      |
                        ..
                        )[last()]
                      )"/>

 <xsl:template match="/*">
  <comp>
   <xsl:apply-templates select="key('kFollowing', generate-id())"/>
   <xsl:apply-templates select="fig[@resumeatnum]"/>
  </comp>
 </xsl:template>

 <xsl:template match="fig">
  <xsl:param name="pStart" select="1"/>

  <fig xml:id="{@xml:id}"/>
   <fignum>1.<xsl:value-of select="position() + $pStart -1"/></fignum>
 </xsl:template>

 <xsl:template match="fig[@resumeatnum]">
   <fig xml:id="{@xml:id}" resumeatnum="{@resumeatnum}"/>
   <fignum>1.<xsl:value-of select="@resumeatnum"/></fignum>
  <xsl:apply-templates select="key('kFollowing', generate-id())">
   <xsl:with-param name="pStart" select="@resumeatnum+1"/>
  </xsl:apply-templates>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<comp>
    <fig xml:id="c1-fig-001"/>
    <fig xml:id="c1-fig-002"/>
    <fig xml:id="c1-fig-003"/>
    <fig xml:id="c1-fig-004" resumeatnum="7"/>
    <fig xml:id="c1-fig-005"/>
    <fig xml:id="c1-fig-006"/>
    <fig xml:id="c1-fig-007" resumeatnum="18"/>
    <fig xml:id="c1-fig-008"/>
    <fig xml:id="c1-fig-009"/>
</comp>

产生了想要的正确结果

<comp>
   <fig xml:id="c1-fig-001"/>
   <fignum>1.1</fignum>
   <fig xml:id="c1-fig-002"/>
   <fignum>1.2</fignum>
   <fig xml:id="c1-fig-003"/>
   <fignum>1.3</fignum>
   <fig xml:id="c1-fig-004" resumeatnum="7"/>
   <fignum>1.7</fignum>
   <fig xml:id="c1-fig-005"/>
   <fignum>1.8</fignum>
   <fig xml:id="c1-fig-006"/>
   <fignum>1.9</fignum>
   <fig xml:id="c1-fig-007" resumeatnum="18"/>
   <fignum>1.18</fignum>
   <fig xml:id="c1-fig-008"/>
   <fignum>1.19</fignum>
   <fig xml:id="c1-fig-009"/>
   <fignum>1.20</fignum>
</comp>
于 2012-07-27T04:42:33.400 回答
0

另一种方法是从匹配第一个fig元素开始

<xsl:apply-templates select="fig[1]"/>

然后你有一个主模板来匹配无花果元素,但有一个参数将保存“递增”值。请注意,它还充当命名模板。

<xsl:template match="fig" name="fig">
   <xsl:param name="sequence" select="1"/>

在此您可以输出您的fignum元素

<fignum>
   <xsl:value-of 
      select="concat(substring-before(substring(@xml:id, 2, string-length(@xml:id) - 1), '-'), '.', $sequence)"/>
</fignum>

然后你会匹配下一个无花果元素,增加参数的值

  <xsl:apply-templates select="following-sibling::fig[1]">
     <xsl:with-param name="sequence" select="$sequence + 1"/>
  </xsl:apply-templates>

要重置序列,您只需有一个与具有相关属性的fig元素匹配的模板,您只需调用具有属性值的命名模板即可覆盖它

<xsl:template match="fig[@resumeatnum != '']">
   <xsl:call-template name="fig">
      <xsl:with-param name="sequence" select="@resumeatnum"/>
   </xsl:call-template>
</xsl:template>

这是完整的 XSLT

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

   <xsl:template match="comp">
      <comp>
         <xsl:apply-templates select="fig[1]"/>
      </comp>
   </xsl:template>

   <xsl:template match="fig[@resumeatnum != '']">
      <xsl:call-template name="fig">
         <xsl:with-param name="sequence" select="@resumeatnum"/>
      </xsl:call-template>
   </xsl:template>

   <xsl:template match="fig" name="fig">
      <xsl:param name="sequence" select="1"/>
      <fig>
         <xsl:apply-templates select="@*"/>
         <fignum>
            <xsl:value-of select="concat(substring-before(substring(@xml:id, 2, string-length(@xml:id) - 1), '-'), '.', $sequence)"/>
         </fignum>
      </fig>
      <xsl:apply-templates select="following-sibling::fig[1]">
         <xsl:with-param name="sequence" select="$sequence + 1"/>
      </xsl:apply-templates>
   </xsl:template>

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

应用于您的示例 XML 时,将输出以下内容

<comp>
   <fig xml:id="c1-fig-001">
      <fignum>1.1</fignum>
   </fig>
   <fig xml:id="c1-fig-002">
      <fignum>1.2</fignum>
   </fig>
   <fig xml:id="c1-fig-003">
      <fignum>1.3</fignum>
   </fig>
   <fig xml:id="c1-fig-004" resumeatnum="7">
      <fignum>1.7</fignum>
   </fig>
   <fig xml:id="c1-fig-005">
      <fignum>1.8</fignum>
   </fig>
   <fig xml:id="c1-fig-006">
      <fignum>1.9</fignum>
   </fig>
   <fig xml:id="c1-fig-007" resumeatnum="18">
      <fignum>1.18</fignum>
   </fig>
   <fig xml:id="c1-fig-008">
      <fignum>1.19</fignum>
   </fig>
   <fig xml:id="c1-fig-009">
      <fignum>1.20</fignum>
   </fig>
</comp>
于 2012-07-26T20:30:36.367 回答
0

像这样的东西可能会起作用

<xsl:for-each select="/comp/fig">
    <fignum>1.<xsl:value-of select="substring(@xml:id,string-length(@xml:id),1)"/>1</fignum>
</xsl:for-each>

有一段时间没有使用 xslt/xpath,所以可能并不完美。基本上只是循环遍历 fig 节点并为最后一个字符添加子字符串。如果要循环的节点超过 9 个,则必须更改子字符串以获取所有数字

于 2012-07-26T16:56:22.817 回答
0

PigChicken,我认为他是在要求基于先前的 [如果存在] resumeatnum 属性具有修改自动增量功能的东西。通过为主要和次要版本组件创建变量,然后将简历中的“偏移量”添加到相应的次要版本,以下内容非常适用于给定的示例。例如,次要版本为 7 的 resumeatnum 为 18 给出的偏移量为 11,它也会添加到以下次要版本中。我使用了 number() 演员表,其中一些可能会被删除。这是变换:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.1" exclude-result-prefixes="" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
    <xsl:template match="/comp">
        <comp>
            <xsl:for-each select="./fig">
                <xsl:copy-of select="."/>
                <xsl:variable name="major">
                    <xsl:value-of select="substring-after(substring-before(./@xml:id,'-'),'c')"/>
                </xsl:variable>
                <xsl:variable name="minor">
                    <xsl:value-of select="number(substring-after(./@xml:id,'fig-'))"/>
                </xsl:variable>
                <xsl:variable name="resume_offset">
                    <xsl:if test="./@resumeatnum">
                        <xsl:value-of select="number(./@resumeatnum - $minor)"/>
                    </xsl:if>
                    <xsl:if test="not(./@resumeatnum)">
                        <xsl:if test="./preceding-sibling::*[@resumeatnum]">
                            <xsl:value-of select="number(./preceding-sibling::*[@resumeatnum][1]/@resumeatnum) - number(substring-after(./preceding-sibling::*[@resumeatnum][1]/@xml:id,'fig-'))"/>
                        </xsl:if>
                        <xsl:if test="not(./preceding-sibling::*[@resumeatnum])">
                            <xsl:value-of select="number(0)"/>
                        </xsl:if>
                    </xsl:if>
                </xsl:variable>
                <fignum>
                    <xsl:value-of select="$major"/>
                    <xsl:text>.</xsl:text>
                    <xsl:value-of select="$minor+$resume_offset"/>
                </fignum>
            </xsl:for-each>
        </comp>
    </xsl:template>
</xsl:stylesheet>
于 2012-07-26T19:26:57.607 回答