xslt查找并插入和/或替换增量编号

时间:2010-11-20 09:38:05

标签: xslt replace

我在xml中有一个术语列表。术语要么具有termtype nd,要么具有pt。如果术语是termtype nd,则它没有ID,而是引用具有ID的termtype PT。我需要做两件事。

  1. 将termId值的XXX替换为termtype nd的增量编号,因此所有术语都有一个id。

  2. 其中termType ND引用termType PT,我需要以某种方式查找其ID并插入它:


  3. <Zthes>
    <term>
    <termName>Term 1</termName>
    <termId>insert new term id N+1 </termId>
    <termType>Nd</termType>
    
     <relation>
     <relationType>USE</relationType>
     <termId>insert ID of term 2 <termID>
    <termName>Term2</termName>
     </relation>
    </term>
    
    <term>
    <termName>Term 2</termName>
    <termId>587889</termId>
    <termType>pt</termType>
     </term>
    
    </zthes>
    

    有谁能指点我如何做到这一点。我对xslt一无所知。我在这里看了一下,找到了关于查找和替换Unique的内容,但根据我对答案的理解,我不认为它适用。

    另外,它不一定是xslt。我与一位开发人员合作,他说这是最好的方法,但是这个答案对他来说太麻烦了。对我来说太困难了!

2 个答案:

答案 0 :(得分:0)

我正在阅读这些内容,但我想我知道你要做什么。

我建议用两个单独的XSL来做这件事。将两个XSL传递组合成一个XSL当然是可能的,但实际的实现取决于你正在使用的XSL库(这里有一些细节,如果你很好奇:http://www.oreillynet.com/xml/blog/2006/08/multistage_xslt_scripts.html

第一遍应该通过您的所有条款,并为标记为“Nd”的条目指定数字。我在猜测:

(a)一旦他们有了ID,他们的类型应该改为“pt”,并且

(b)这些要素的顺序并不具体。

我建议将此作为单独传递的原因是你的一个术语可能引用另一个本身就是'Nd'类型的术语。如果是这种情况,那么就没有可供参考的有效数字(因为还没有分配)

执行此步骤的XSL将是这样的:

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

    <xsl:template match="term[termType = 'Nd']">
        <term>
            <xsl:copy-of select="termName"/>
            <termId><xsl:value-of select="position()"/></termId>
            <termType>pt</termType>
            <xsl:copy-of select="relation" />
        </term>
    </xsl:template>

    <xsl:template match="/">
        <zthes>
            <xsl:apply-templates select="zthes/term[termType = 'Nd']"/>
            <xsl:copy-of select="zthes/term[termType = 'pt']"/>
        </zthes>
    </xsl:template>

</xsl:stylesheet>

第二步是获取该变换的输出,并将其推送到第二个变换,该变换将“填充”'关系'术语的ID。这是一个相当直接的身份(精确,递归复制)转换,其中有一个特殊规则。特殊规则标识关系节点内的termIds,并根据名称匹配替换正确的termId。此转换如下所示:

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

    <xsl:template match="relation/termId">
        <termId>
            <xsl:value-of select="/zthes/term[termName=current()/../termName]/termId"/>
        </termId>
    </xsl:template>

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

</xsl:stylesheet>

我希望这会大致完成你所追求的目标。但它不能按原样输入您当前的输入数据,因为您当前的输入实际上是无效的xml。 :)修复它:

  • 将“Zthes”更改为“zthes” 打开标签。 XML区分大小写
  • 在第一个'关系'区块内,确保关闭'termId' 节点。目前你正在开放 它两次而不是关闭它。
  • 在'relation'块的'termName'中,您引用了'Term2' 当你的意思是'第2学期'。 有一个空白区别 将阻止他们匹配。
祝你好运!

答案 1 :(得分:0)

转换

<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:key name="ktermPtIdByName"
      match="term[termType='pt']/termId"
      use="../termName"/>

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

 <xsl:template match="term[termType='Nd']/termId">
  <termId>
    <xsl:number level="single" count="/*/term[termType='Nd']"/>
  </termId>
 </xsl:template>

 <xsl:template match="relation/termId">
  <termId>
    <xsl:value-of select="key('ktermPtIdByName', ../termName)"/>
  </termId>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档(您的XML,但已修正为语法结构良好且语义正确,然后放大两倍以使其更有趣):

<zthes>
    <term>
        <termName>Term 1</termName>
        <termId></termId>
        <termType>Nd</termType>
        <relation>
            <relationType>USE</relationType>
            <termId></termId>
            <termName>Term 2</termName>
        </relation>
    </term>
    <term>
        <termName>Term 2</termName>
        <termId>587889</termId>
        <termType>pt</termType>
    </term>
    <term>
        <termName>Term 3</termName>
        <termId></termId>
        <termType>Nd</termType>
        <relation>
            <relationType>USE</relationType>
            <termId></termId>
            <termName>Term 4</termName>
        </relation>
    </term>
    <term>
        <termName>Term 4</termName>
        <termId>587890</termId>
        <termType>pt</termType>
    </term>
</zthes>

生成想要的正确结果

<zthes>
   <term>
      <termName>Term 1</termName>
      <termId>1</termId>
      <termType>Nd</termType>
      <relation>
         <relationType>USE</relationType>
         <termId>587889</termId>
         <termName>Term 2</termName>
      </relation>
   </term>
   <term>
      <termName>Term 2</termName>
      <termId>587889</termId>
      <termType>pt</termType>
   </term>
   <term>
      <termName>Term 3</termName>
      <termId>2</termId>
      <termType>Nd</termType>
      <relation>
         <relationType>USE</relationType>
         <termId>587890</termId>
         <termName>Term 4</termName>
      </relation>
   </term>
   <term>
      <termName>Term 4</termName>
      <termId>587890</termId>
      <termType>pt</termType>
   </term>
</zthes>

请注意

  1. 标识规则用于“按原样”复制每个节点。

  2. 模板仅覆盖需要修改的元素的标识规则。

  3. <xsl:number>用于(我是懒惰的)计算所需的termId。

  4. 使用密钥通过termId

  5. 最有效地查找TermName