XSLT 1.0:重命名具有相同内容的元素 [英] XSLT 1.0: rename elements with same content

查看:103
本文介绍了XSLT 1.0:重命名具有相同内容的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是一件容易的事,但我现在完全陷入困境.我有以下XML:

It seemed like an easy task but I am totally stuck now. I have the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<Items>
<Item>
    <ITEM_CODE>ITEM_CODE</ITEM_CODE>
    <ITEM_NAME>ITEM_NAME</ITEM_NAME>
    <ITEM_ALTERNATE_NAME>ITEM_ALTERNATE_NAME</ITEM_ALTERNATE_NAME>
    <ITEM_CATEGORY_CODE>ITEM_CATEGORY_CODE</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>15031</ITEM_CODE>
    <ITEM_NAME>Outer Carton</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150529</ITEM_CODE>
    <ITEM_NAME>Outer Carton</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150999</ITEM_CODE>
    <ITEM_NAME>Outer Carton</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150988</ITEM_CODE>
    <ITEM_NAME>test</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
</Items>

如果<ITEM_NAME>元素的内容重复,则应使用后缀重命名,例如一个计数器值.我想出了这个XSLT:

If <ITEM_NAME> elements have duplicate contents those should be renamed with a suffix, e.g. a counter value. I came up with this XSLT:

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

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

<xsl:output encoding="UTF-8" method="xml" indent="yes"/>

<xsl:key name="keyItemName" match="Item" use="concat(ITEM_CODE , '|', ITEM_NAME)"/>

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

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

<xsl:template match="ITEM_NAME">

    <xsl:for-each select="parent::Item[generate-id()=generate-id(key('keyItemName',concat(ITEM_CODE , '|', ITEM_NAME))[1])]">
        <xsl:variable name="number">
            <xsl:number/>
        </xsl:variable>
        <ITEM_NAME>
            <xsl:value-of select="concat(ITEM_NAME,'-',$number)"/>
        </ITEM_NAME>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

它给了我这个输出:

<?xml version="1.0" encoding="UTF-8"?>
<Items>
<Item>
    <ITEM_CODE>ITEM_CODE</ITEM_CODE>
    <ITEM_NAME>ITEM_NAME-1</ITEM_NAME>
    <ITEM_ALTERNATE_NAME>ITEM_ALTERNATE_NAME</ITEM_ALTERNATE_NAME>
    <ITEM_CATEGORY_CODE>ITEM_CATEGORY_CODE</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>15031</ITEM_CODE>
    <ITEM_NAME>Outer Carton-2</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150529</ITEM_CODE>
    <ITEM_NAME>Outer Carton-3</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150999</ITEM_CODE>
    <ITEM_NAME>Outer Carton-4</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150988</ITEM_CODE>
    <ITEM_NAME>test-5</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
</Items>

但是我希望得到这样的输出:

But I expect this output:

<?xml version="1.0" encoding="UTF-8"?>
<Items>
<Item>
    <ITEM_CODE>ITEM_CODE</ITEM_CODE>
    <ITEM_NAME>ITEM_NAME</ITEM_NAME>
    <ITEM_ALTERNATE_NAME>ITEM_ALTERNATE_NAME</ITEM_ALTERNATE_NAME>
    <ITEM_CATEGORY_CODE>ITEM_CATEGORY_CODE</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>15031</ITEM_CODE>
    <ITEM_NAME>Outer Carton-2</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150529</ITEM_CODE>
    <ITEM_NAME>Outer Carton-3</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150999</ITEM_CODE>
    <ITEM_NAME>Outer Carton-4</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
<Item>
    <ITEM_CODE>150988</ITEM_CODE>
    <ITEM_NAME>test</ITEM_NAME>
    <ITEM_ALTERNATE_NAME/>
    <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
</Item>
</Items>

在最后一个<Item>中,ITEM_NAME不应重命名,因为它没有被称为外纸箱".同样,在第一个<Item>元素中,不应重命名.

In the last <Item> the ITEM_NAME should not be renamed because it is not called "Outer Carton". Also in the first <Item> element no renaming should be happening.

我已经接近解决方案,但是我无法解决它.有人可以帮忙吗-非常感谢!

I am close to the solution but I just can't get around to it. Can someone please help - thanks a lot!

最诚挚的问候, 彼得

推荐答案

您当前的密钥似乎加入了 ITEM_NAME ITEM_CODE ,但是您似乎只想要 ITEM_NAME 在这里

You current key seems to join ITEM_NAME and ITEM_CODE, but it looks like you only want ITEM_NAME here

<xsl:key name="keyItemName" match="ITEM_NAME" use="."/>

您似乎还希望后缀的编号基于父 item 元素的位置.实现此目的的一种方法是拥有一个与 item 元素匹配的模板,然后将数字作为参数传递给后续的数学模板

It also looks like you want the numbering for the suffix to be based on the position of the parent item element. One way to achieve this is to have a template to match the item element, and then pass the number as a parameter to the subsequent mathching templates

<xsl:template match="Item">
   <Item>
      <xsl:apply-templates select="@*|node()">
          <xsl:with-param name="number">
            <xsl:number/>
         </xsl:with-param>
      </xsl:apply-templates>
   </Item>
</xsl:template>

然后,您需要一个模板来匹配发生重复的 ITEM_NAME 元素.只需检查组中至少有第二个为密钥定义的元素,即可完成此操作:

Then, you need a template to match ITEM_NAME elements for which duplicate occurs. This can be done simply by checking there is at least a second element defined in the group for the key:

<xsl:template match="ITEM_NAME[key('keyItemName', .)[2]]">
   <xsl:param name="number"/>

然后,您只需输出带有后缀的元素即可.

Then, you can just output the element with the suffix.

这是完整的XSLT

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

   <xsl:key name="keyItemName" match="ITEM_NAME" use="."/>

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

   <xsl:template match="Item">
      <Item>
         <xsl:apply-templates select="@*|node()">
            <xsl:with-param name="number">
               <xsl:number/>
            </xsl:with-param>
         </xsl:apply-templates>
      </Item>
   </xsl:template>

   <xsl:template match="ITEM_NAME[key('keyItemName', .)[2]]">
      <xsl:param name="number"/>
      <ITEM_NAME>
         <xsl:value-of select="concat(.,'-',$number)"/>
      </ITEM_NAME>
   </xsl:template>
</xsl:stylesheet>

应用于XML时,将输出以下内容

When applied to your XML, the following is output

<Items>
   <Item>
      <ITEM_CODE>ITEM_CODE</ITEM_CODE>
      <ITEM_NAME>ITEM_NAME</ITEM_NAME>
      <ITEM_ALTERNATE_NAME>ITEM_ALTERNATE_NAME</ITEM_ALTERNATE_NAME>
      <ITEM_CATEGORY_CODE>ITEM_CATEGORY_CODE</ITEM_CATEGORY_CODE>
   </Item>
   <Item>
      <ITEM_CODE>15031</ITEM_CODE>
      <ITEM_NAME>Outer Carton-2</ITEM_NAME>
      <ITEM_ALTERNATE_NAME/>
      <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
   </Item>
   <Item>
      <ITEM_CODE>150529</ITEM_CODE>
      <ITEM_NAME>Outer Carton-3</ITEM_NAME>
      <ITEM_ALTERNATE_NAME/>
      <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
   </Item>
   <Item>
      <ITEM_CODE>150999</ITEM_CODE>
      <ITEM_NAME>Outer Carton-4</ITEM_NAME>
      <ITEM_ALTERNATE_NAME/>
      <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
   </Item>
   <Item>
      <ITEM_CODE>150988</ITEM_CODE>
      <ITEM_NAME>test</ITEM_NAME>
      <ITEM_ALTERNATE_NAME/>
      <ITEM_CATEGORY_CODE>52401</ITEM_CATEGORY_CODE>
   </Item>
</Items>

这篇关于XSLT 1.0:重命名具有相同内容的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆