Combining XML using XSLT 1.0 [duplicate]

断了今生、忘了曾经 提交于 2019-12-13 08:59:18

问题


I need to map the following but its difficult because it has different names:

<main>
    <order>
        <ID>123</ID>
        <Name>ABC</Name>
    </order>
    <order>
        <ID>4556</ID>
        <Name>AAA</Name>
        <ParentID>123</ParentID>
    </order>
</main>

The result should be:

<main>
    <order>
        <ID>123</ID>
        <Name>ABC</Name>
        <order>
            <ID>4556</ID>
            <Name>AAA</Name>
            <ParentID>123</ParentID>
        </order>
    </order>
</main>

回答1:


Like @michael.hor257k said, conceptually this question is the same as your previous question. I think you're just not understanding the concept. Hopefully the comments in my example will help.

If I understand the question correctly, you want to nest order elements inside of their "parent" order element based on ParentID. Since we're basing it on the ParentID, that's what we'll use for our key...

XML Input

<main>
    <order>
        <ID>123</ID>
        <Name>ABC</Name>
    </order>

    <order>
        <ID>4556</ID>
        <Name>AAA</Name>
        <ParentID>123</ParentID>
    </order>
</main>

XSLT 1.0

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

  <!--Create a key containing order elements that contain a non-empty ParentID.-->
  <xsl:key name="orderByParentId" match="order[string(ParentID)]" use="ParentID"/>

  <!--Identity transform (https://www.w3.org/TR/xslt#copying)-->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/main">
    <xsl:copy>
      <!--To get the high level order elements, only apply-templates when order
      does not contain a non-empty ParentID child.-->
      <xsl:apply-templates 
        select="@*|order[not(string(ParentID))]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="order">
    <xsl:copy>
      <!--Don't apply-templates to ParentID; we don't want to keep those.
      Do apply-templates to the key 'orderByParentId' when the key matches
      the current order's ID child.-->
      <xsl:apply-templates 
        select="@*|*[not(self::ParentID)]|key('orderByParentId',ID)"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Output

<main>
   <order>
      <ID>123</ID>
      <Name>ABC</Name>
      <order>
         <ID>4556</ID>
         <Name>AAA</Name>
      </order>
   </order>
</main>



回答2:


One approach to copy all order nodes with index n>1 into the first one is the following XSLT:

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

    <xsl:template match="text()" />    <!-- suppresses copying of text() nodes -->

    <xsl:template match="main">        <!-- replicates the "main" node -->
      <main>
        <xsl:apply-templates />
      </main>
    </xsl:template>

    <xsl:template match="order[1]">    <!-- matches the first "order" node and copies all following ones -->
      <order>
        <xsl:copy-of select="*" />
        <xsl:copy-of select="following-sibling::order" />
      </order>   
    </xsl:template>    
</xsl:stylesheet>

The output looks like this:

<?xml version="1.0"?>
<main>
    <order>
        <ID>123</ID>
        <Name>ABC</Name>
        <order>
            <ID>4556</ID>
            <Name>AAA</Name>
            <ParentID>123</ParentID>
        </order>
    </order>
</main>


来源:https://stackoverflow.com/questions/40493838/combining-xml-using-xslt-1-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!