2011-06-17 118 views
2

我有一个XML,如下所示。哪里有不同的项目来删除或添加。每个项目都会有序列号。我想要做的是我想从这些输入中准备一个新的XML,如果一个项目代码的项目来添加和删除我想合并成一个单一的项目节点。形成的新项目将有行动代码作为更新和中国将是增加项目中国和老年将是删除项目中国。使用XSLT合并重复节点以形成新的XML

INPUT

`


<ITEM> 
    <SINO>1</SINO> 
    <ITEMCODE>101</ITEMNAME> 
    <ACTION>ADD</ACTION> 
    <OLDSINO></OLDSINO> 
</ITEM> 
<ITEM> 
    <SINO>2</SINO> 
    <ITEMCODE>101</ITEMNAME> 
    <ACTION>DELETE</ACTION> 
    <OLDSINO></OLDSINO> 
</ITEM> 
<ITEM> 
    <SINO>3</SINO> 
    <ITEMCODE>102</ITEMNAME> 
    <ACTION>ADD</ACTION> 
    <OLDSINO></OLDSINO> 
</ITEM> 
<ITEM> 
    <SINO>4</SINO> 
    <ITEMCODE>103</ITEMNAME> 
    <ACTION>ADD</ACTION> 
    <OLDSINO></OLDSINO> 
</ITEM> 
<ITEM> 
    <SINO>5</SINO> 
    <ITEMCODE>103</ITEMNAME> 
    <ACTION>DELETE</ACTION> 
    <OLDSINO></OLDSINO> 
</ITEM> 
<ITEM> 
    <SINO>6</SINO> 
    <ITEMCODE>104</ITEMNAME> 
    <ACTION>DELETE</ACTION> 
    <OLDSINO></OLDSINO> 
</ITEM> 

'

OUTPUT

`


<ITEM> 
    <SINO>1</SINO> 
    <ITEMCODE>101</ITEMNAME> 
    <ACTION>UPDATE</ACTION> 
    <OLDSINO>2</OLDSINO> 
</ITEM> 
<ITEM> 
    <SINO>3</SINO> 
    <ITEMCODE>102</ITEMNAME> 
    <ACTION>ADD</ACTION> 
    <OLDSINO></OLDSINO> 
</ITEM> 
<ITEM> 
    <SINO>4</SINO> 
    <ITEMCODE>103</ITEMNAME> 
    <ACTION>DELETE</ACTION> 
    <OLDSINO>5</OLDSINO> 
</ITEM> 
<ITEM> 
    <SINO>6</SINO> 
    <ITEMCODE>104</ITEMNAME> 
    <ACTION>DELETE</ACTION> 
    <OLDSINO></OLDSINO> 
</ITEM> 

`

任何想法如何达致这使用XSLT。

+0

+1好问题(即使输出样本根据您的描述不正确)。 – 2011-06-17 11:44:05

+1

我的意思是第三个ITEM/ACTION元素应该是UPDATE。 – 2011-06-17 12:00:55

+0

好问题,+1。根据最基本的XSLT设计模式查看我的答案,以获得完整高效的解决方案 - 重写身份规则/模板。 – 2011-06-17 16:35:40

回答

0

校正错字(开口ITEMCODE标记与结束ITEMNAME标签),并与项目的根元素的工作的完整XSLT可以是:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="deletes" match="ITEM[ACTION='DELETE']" use="ITEMCODE/text()"/> 
    <xsl:key name="adds" match="ITEM[ACTION='ADD']" use="ITEMCODE/text()"/> 

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


    <xsl:template match="ITEM[ACTION='ADD' and key('deletes',ITEMCODE/text())]"> 
     <xsl:variable name="current" select="ITEMCODE/text()"/> 
     <xsl:copy> 
      <xsl:for-each select="*"> 
      <xsl:choose> 
       <xsl:when test="name()='ACTION'"> 
       <ACTION>UPDATE</ACTION> 
       </xsl:when> 
       <xsl:when test="name()='OLDSINO'"> 
       <OLDSINO><xsl:value-of select="key('deletes',$current)/SINO/text()"/></OLDSINO> 
       </xsl:when> 
       <xsl:otherwise> 
       <xsl:copy-of select="." /> 
       </xsl:otherwise> 
      </xsl:choose> 
      </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ITEM[ACTION='ADD' and not(key('deletes',ITEMCODE/text()))]"> 
    <xsl:copy-of select="." /> 
    </xsl:template> 

    <xsl:template match="ITEM[ACTION='DELETE' and not(key('adds',ITEMCODE/text()))]"> 
    <xsl:copy-of select="." /> 
    </xsl:template> 

    <xsl:template match="ITEM" /> 

    </xsl:stylesheet> 
+1

该变换的产生输出保存一个空的“OLDSINO”元素。请改正。 – 2011-06-17 11:52:55

+0

现在已更正 – 2011-06-17 21:56:26

1

如果与项目码的项目已经到来添加和删​​除我想合并成一个单一的项目节点。形成将有动作代码更新和中美关系的新项目将加入项目中,并oldsino将删除项目中

该解决方案主要起到对兄弟姐妹模板匹配模式,并利用该身份规则。

XSLT 1。0

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

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

    <xsl:template match="ITEM[ 
      ITEMCODE[../ACTION='ADD'] 
     = 
       ../ITEM/ITEMCODE[../ACTION='DELETE']]"> 
     <xsl:copy> 
      <SINO><xsl:value-of select="../ITEM[ITEMCODE 
        =current()/ITEMCODE and ACTION='ADD']/ 
        SINO"/> 
      </SINO> 
      <xsl:copy-of select="ITEMCODE"/> 
      <ACTION>UPDATE</ACTION> 
      <OLDSINO><xsl:value-of select="../ITEM[ITEMCODE 
        =current()/ITEMCODE and ACTION='DELETE']/ 
        SINO"/> 
      </OLDSINO>   
     </xsl:copy> 
      </xsl:template> 

      <xsl:template match="ITEM[ 
      ITEMCODE[../ACTION='DELETE'] 
     = 
       ../ITEM/ITEMCODE[../ACTION='ADD']]"/> 


</xsl:stylesheet> 

的溶液生产:

<?xml version="1.0" encoding="UTF-16"?> 
<ITEMS> 
    <ITEM> 
     <SINO>1</SINO> 
     <ITEMCODE>101</ITEMCODE> 
     <ACTION>UPDATE</ACTION> 
     <OLDSINO>2</OLDSINO> 
    </ITEM> 
    <ITEM> 
     <SINO>3</SINO> 
     <ITEMCODE>102</ITEMCODE> 
     <ACTION>ADD</ACTION> 
     <OLDSINO></OLDSINO> 
    </ITEM> 
    <ITEM> 
     <SINO>4</SINO> 
     <ITEMCODE>103</ITEMCODE> 
     <ACTION>UPDATE</ACTION> 
     <OLDSINO>5</OLDSINO> 
    </ITEM> 
    <ITEM> 
     <SINO>6</SINO> 
     <ITEMCODE>104</ITEMCODE> 
     <ACTION>DELETE</ACTION> 
     <OLDSINO></OLDSINO> 
    </ITEM> 
</ITEMS> 
+0

如果在同一个ITEMCODE上有多个“ADD”或“DELETE”操作,并且没有*“ADD”和“DELETE”操作,则此解决方案会产生什么结果?同样的'ITEMCODE'?我认为这段代码对XML文档做了太多的假设 - 可能或可能不是真的。 – 2011-06-17 13:27:56

+0

@ Dimitre-Novatchev:我会更好地检查;即使假设是基于粗略的OP描述,你也可能是真的。无论如何,如果应用于OP输入样本,它工作得很好。 – 2011-06-17 13:38:08

+0

@ Dimitre-Novatchev:我已经改变了一点,使其更一般。不管理同一ITEMCODE的多个ADD,但没有提及OP来管理这种情况。 – 2011-06-17 14:07:47

1

下面是一个简短和简单的解决方案,它覆盖身份规则/模板:

<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="kItemByCode" match="ITEM" 
    use="ITEMCODE"/> 

<xsl:key name="kActionByCode" match="ACTION" 
    use="../ITEMCODE"/> 

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

<xsl:template match= 
    "ITEM[not(generate-id() = 
      generate-id(key('kItemByCode', ITEMCODE)[1]) 
      ) 
     ]"/> 

<xsl:template match= 
    "ITEM[generate-id() = 
     generate-id(key('kItemByCode', ITEMCODE)[1]) 
     and 
     key('kActionByCode', ITEMCODE) = 'ADD' 
     and 
     key('kActionByCode', ITEMCODE) = 'DELETE' 
     ] 
     /ACTION/text() 
    "> 
     <xsl:text>UPDATE</xsl:text> 
    </xsl:template> 

<xsl:template match= 
    "ITEM[generate-id() = 
     generate-id(key('kItemByCode', ITEMCODE)[1]) 
     and 
     key('kActionByCode', ITEMCODE) = 'ADD' 
     and 
     key('kActionByCode', ITEMCODE) = 'DELETE' 
     ] 
     /OLDSINO 
    "> 
    <OLDSINO> 
    <xsl:apply-templates mode="List" 
     select="key('kItemByCode', ../ITEMCODE)[position()>1]" /> 
    </OLDSINO> 
    </xsl:template> 

<xsl:template match="ITEM" mode="List"> 
    <xsl:if test="not(position()=1)">,</xsl:if> 
    <xsl:value-of select="SINO"/> 
</xsl:template> 
</xsl:stylesheet> 

当该变换被应用上以下XML文档(基于并纠正提供的严重畸形X ML片段):

<t> 
    <ITEM> 
     <SINO>1</SINO> 
     <ITEMCODE>101</ITEMCODE> 
     <ACTION>ADD</ACTION> 
     <OLDSINO></OLDSINO> 
    </ITEM> 
    <ITEM> 
     <SINO>2</SINO> 
     <ITEMCODE>101</ITEMCODE> 
     <ACTION>DELETE</ACTION> 
     <OLDSINO></OLDSINO> 
    </ITEM> 
    <ITEM> 
     <SINO>3</SINO> 
     <ITEMCODE>102</ITEMCODE> 
     <ACTION>ADD</ACTION> 
     <OLDSINO></OLDSINO> 
    </ITEM> 
    <ITEM> 
     <SINO>4</SINO> 
     <ITEMCODE>103</ITEMCODE> 
     <ACTION>ADD</ACTION> 
     <OLDSINO></OLDSINO> 
    </ITEM> 
    <ITEM> 
     <SINO>5</SINO> 
     <ITEMCODE>103</ITEMCODE> 
     <ACTION>DELETE</ACTION> 
     <OLDSINO></OLDSINO> 
    </ITEM> 
    <ITEM> 
     <SINO>6</SINO> 
     <ITEMCODE>104</ITEMCODE> 
     <ACTION>DELETE</ACTION> 
     <OLDSINO></OLDSINO> 
    </ITEM> 
</t> 

想要的,正确的结果产生:

<t> 
    <ITEM> 
    <SINO>1</SINO> 
    <ITEMCODE>101</ITEMCODE> 
    <ACTION>UPDATE</ACTION> 
    <OLDSINO>2</OLDSINO> 
    </ITEM> 
    <ITEM> 
    <SINO>3</SINO> 
    <ITEMCODE>102</ITEMCODE> 
    <ACTION>ADD</ACTION> 
    <OLDSINO /> 
    </ITEM> 
    <ITEM> 
    <SINO>4</SINO> 
    <ITEMCODE>103</ITEMCODE> 
    <ACTION>UPDATE</ACTION> 
    <OLDSINO>5</OLDSINO> 
    </ITEM> 
    <ITEM> 
    <SINO>6</SINO> 
    <ITEMCODE>104</ITEMCODE> 
    <ACTION>DELETE</ACTION> 
    <OLDSINO /> 
    </ITEM> 
</t> 

说明

  1. 身份规则/模板拷贝的每一个节点“原样是”。

  2. 空体的模板覆盖的一组ITEM元件的每一个非第一ITEM具有相同ITEMCODE身份规则 - 任何这样的节点不被复制到输出(又名删除)。

  3. 第三模板覆盖为每ITEM元素是一组ITEM元件的在所述第一与所述相同ITEMCODE身份规则和对于其ITEMCODE存在与ACTION项两者“ADD”和“删除”。它通过将模板“列表”中的模板应用于组中的所有ITEM元素来构造必要的OLDSINO元素,但是是第一个元素。

  4. 使用Muenchian的分组方法和一般的密钥,以便实现高效紧凑的实现。

  5. 此解决方案可以与ITEM元素的任意混合物正确工作,这些元素可能具有相同的ITEMCODE

+0

该解决方案不能完全满足OLDSINO元素正确填充的OP要求。 – 2011-06-17 13:36:39

+0

@empo:您的评论是在旧的答案中做出的,不再是真实的 - 请查看更新后的解决方案。 – 2011-06-17 13:44:40

+0

我在这篇文章的输出中仍然看到空的OLDSINO元素。 – 2011-06-17 13:56:30