使用XSLT进行节点重组

时间:2012-09-02 05:26:30

标签: xslt

我的输入xml有很少的节点没有正确的分组..它们只是串行方式。 我需要创建一个父节点,并使用XSLT将它们放在以下结构中....我没有任何运气。反过来似乎很容易。任何人都可以帮助快速XSLT。

感谢您的时间

Input.xml文件

<root>
 <info>
  <name>papa</name>
  <age>10</age>

   <groupkey>1</groupkey>
   <groupkey>2</groupkey>
   <groupkey>2</groupkey>


   <groupname>n1</groupname>
   <groupname>n2</groupname>
   <groupname>n3</groupname>



 </info>
</root>

欲望输出

<root>
 <info>
  <name>papa</name>
  <age>10</age>

     <groups>

       <group>
          <groupkey>1</groupkey>
          <groupname>n1</groupname>
       </group>

      <group>
          <groupkey>2</groupkey>
          <groupname>n2</groupname>
       </group>

       <group>
          <groupkey>3</groupkey>
          <groupname>n3</groupname>
       </group>



     </groups>

 </info>
</root>

添加以下

非常感谢Novatchev。我测试了它,正是我想要的。它也是通用的。
最后一个问题请。如果我有另一个名为address的节点,请跟我如何合并它。请帮忙。 谢谢你的时间。

输入

<root>
 <info>
  <name>papa</name>
  <age>10</age>

    <groupkey>1</groupkey>
    <groupkey>2</groupkey>
    <groupkey>3</groupkey>

    <groupname>n1</groupname>
    <groupname>n2</groupname>
    <groupname>n3</groupname>



    <addresskey>1</addresskey>
    <addresskey>2</addresskey>
    <addresskey>3</addresskey>

    <addressname>a1</addressname>
    <addressname>a2</addressname>
    <addressname>a3</addressname>  


 </info>
</root>

输出

<root>
 <info>
  <name>papa</name>
  <age>10</age>

     <groups>

       <group>
          <groupkey>1</groupkey>
          <groupname>n1</groupname>
       </group>

      <group>
          <groupkey>2</groupkey>
          <groupname>n2</groupname>
       </group>

       <group>
          <groupkey>3</groupkey>
          <groupname>n3</groupname>
       </group>

     </groups>


      <addresses>

            <address>
               <addresskey>1</addresskey>
               <addressname>a1</addressname>
            </address>

           <address>
               <addresskey>2</addresskey>
               <addressname>a2</addressname>
            </address>

            <address>
               <addresskey>3</addresskey>
               <addressname>a3</addressname>
            </address>

     </addresses>



 </info>
</root>

1 个答案:

答案 0 :(得分: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:template match="node()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="age">
  <xsl:call-template name="identity"/>
  <groups>
    <xsl:apply-templates select="following-sibling::groupkey" mode="grouping"/>
  </groups>
 </xsl:template>

 <xsl:template match="groupkey" mode="grouping">
  <group>
    <xsl:variable name="vPos" select="position()"/>
    <xsl:call-template name="identity"/>
    <xsl:apply-templates mode="grouping" select="../groupname[$vPos]"/>
  </group>
 </xsl:template>

 <xsl:template match="groupname" mode="grouping">
   <xsl:call-template name="identity"/>
 </xsl:template>

 <xsl:template match="groupkey|groupname"/>
</xsl:stylesheet>

应用于提供的XML文档(已更正的第3个groupkey):

<root>
 <info>
  <name>papa</name>
  <age>10</age>

   <groupkey>1</groupkey>
   <groupkey>2</groupkey>
   <groupkey>3</groupkey>

   <groupname>n1</groupname>
   <groupname>n2</groupname>
   <groupname>n3</groupname>

 </info>
</root>

生成想要的正确结果

<root>
   <info>
      <name>papa</name>
      <age>10</age>
      <groups>
         <group>
            <groupkey>1</groupkey>
            <groupname>n1</groupname>
         </group>
         <group>
            <groupkey>2</groupkey>
            <groupname>n2</groupname>
         </group>
         <group>
            <groupkey>3</groupkey>
            <groupname>n3</groupname>
         </group>
      </groups>
   </info>
</root>

<强>更新

与此同时,OP通过添加XML文档中存在第二类数据(地址信息)的要求更新了问题,并且必须进行类似的分组。

以下是更新的解决方案

<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()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="age">
  <xsl:call-template name="identity"/>
  <groups>
    <xsl:apply-templates select="following-sibling::groupkey" mode="grouping"/>
  </groups>
  <addresses>
    <xsl:apply-templates select="following-sibling::addresskey" mode="grouping"/>
  </addresses>

 </xsl:template>

 <xsl:template match="groupkey" mode="grouping">
  <group>
    <xsl:variable name="vPos" select="position()"/>
    <xsl:call-template name="identity"/>
    <xsl:apply-templates mode="grouping" select="../groupname[$vPos]"/>
  </group>
 </xsl:template>

 <xsl:template match="addresskey" mode="grouping">
  <address>
    <xsl:variable name="vPos" select="position()"/>
    <xsl:call-template name="identity"/>
    <xsl:apply-templates mode="grouping" select="../addressname[$vPos]"/>
  </address>
 </xsl:template>

 <xsl:template match="groupname|addressname" mode="grouping">
   <xsl:call-template name="identity"/>
 </xsl:template>

 <xsl:template match="groupkey|groupname|addresskey|addressname"/>
</xsl:stylesheet>

将此转换应用于新指定的XML文档

<root>
 <info>
  <name>papa</name>
  <age>10</age>

    <groupkey>1</groupkey>
    <groupkey>2</groupkey>
    <groupkey>3</groupkey>

    <groupname>n1</groupname>
    <groupname>n2</groupname>
    <groupname>n3</groupname>



    <addresskey>1</addresskey>
    <addresskey>2</addresskey>
    <addresskey>3</addresskey>

    <addressname>a1</addressname>
    <addressname>a2</addressname>
    <addressname>a3</addressname>


 </info>
</root>

再次生成想要的正确结果:

<root>
   <info>
      <name>papa</name>
      <age>10</age>
      <groups>
         <group>
            <groupkey>1</groupkey>
            <groupname>n1</groupname>
         </group>
         <group>
            <groupkey>2</groupkey>
            <groupname>n2</groupname>
         </group>
         <group>
            <groupkey>3</groupkey>
            <groupname>n3</groupname>
         </group>
      </groups>
      <addresses>
         <address>
            <addresskey>1</addresskey>
            <addressname>a1</addressname>
         </address>
         <address>
            <addresskey>2</addresskey>
            <addressname>a2</addressname>
         </address>
         <address>
            <addresskey>3</addresskey>
            <addressname>a3</addressname>
         </address>
      </addresses>
   </info>
</root>