XSL转换中的节点顺序

时间:2013-08-05 14:57:38

标签: xslt xslt-1.0

我有一个xml,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Object>
<Data type="plan" name="testAom" id="10">

    <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-1" operation="create" >
        <p name="Active">1</p>
        <p name="Type">CPU</p>
        <p name="StDate">2013-07-27T00:00:00+00:00</p>
        <p name="StpDate">2013-07-29T00:00:00+00:00</p>
    </obj>

    <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-1/E-1" operation="create">
        <p name="dayOfWeek">0</p>
        <p name="interval">10</p>
    </obj>

    <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-2/E-1" operation="update">
        <p name="dayOfWeek">0</p>
        <p name="interval">10</p>
    </obj>

    <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-2" operation="update">
        <p name="Active">1</p>
        <p name="Type">CPU</p>
        <p name="StDate">2013-07-27T00:00:00+00:00</p>
        <p name="StpDate">2013-07-29T00:00:00+00:00</p>
    </obj>
</Data>
</Object>

此处不保证输入源文件的顺序。但是在XSL转换后的输出中,我要求输出按特定顺序。

以下是XSL:

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

<xsl:output method="xml" indent="yes"/>

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

<xsl:template match="obj[@class = 'D' ]">
<xsl:variable name="item" select="."/>
<xsl:choose>
    <xsl:when test="$item/@operation='update'">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="operation">delete</xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="operation">create</xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:when>
    <xsl:otherwise>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="operation">NEW_create</xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="obj[@class = 'E' ]">
<xsl:variable name="childitem" select="."/>
<xsl:choose>
    <xsl:when test="$childitem/@operation='update'">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="operation">delete</xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="operation">create</xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:when>
    <xsl:otherwise>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="operation">NEW_create</xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:otherwise>
</xsl:choose>
</xsl:template>         
</xsl:stylesheet>

我得到的输出是:

<?xml version="1.0" encoding="UTF-8"?>
<Object>
<Data type="plan" name="testAom" id="10">

    <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-1" operation="NEW_create">
        <p name="Active">1</p>
        <p name="Type">CPU</p>
        <p name="StDate">2013-07-27T00:00:00+00:00</p>
        <p name="StpDate">2013-07-29T00:00:00+00:00</p>
    </obj>

    <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-1/E-1" operation="NEW_create">
        <p name="dayOfWeek">0</p>
        <p name="interval">10</p>
    </obj>

    <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-2/E-1" operation="delete">
        <p name="dayOfWeek">0</p>
        <p name="interval">10</p>
    </obj>
    <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-2/E-1" operation="create">
        <p name="dayOfWeek">0</p>
        <p name="interval">10</p>
    </obj>

    <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-2" operation="delete">
        <p name="Active">1</p>
        <p name="Type">CPU</p>
        <p name="StDate">2013-07-27T00:00:00+00:00</p>
        <p name="StpDate">2013-07-29T00:00:00+00:00</p>
    </obj>
    <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-2" operation="create">
        <p name="Active">1</p>
        <p name="Type">CPU</p>
        <p name="StDate">2013-07-27T00:00:00+00:00</p>
        <p name="StpDate">2013-07-29T00:00:00+00:00</p>
    </obj>
</Data>
</Object>

操作属性“更新”时,我需要执行删除并创建。

上述节点具有基于属性 distName 的父子关系,即 A-1 / B-1 / C-1 / D-1 是<的父级强> A-1 / B-1 / C-1 / d-1 / E-1 即可。 为了使更新操作正常工作,我首先需要父创建和删除,然后是子删除并始终创建。

无论输入源xml文件的顺序如何,如何实现?

即。具有类属性 D 的obj节点应首先按顺序排列,而不是 E

预期输出XML:

<?xml version="1.0"?>
<Object>
<Data type="plan" name="testAom" id="10">
<obj class="D" version="1.0" distName="A-1/B-1/C-1/D-1" operation="NEW_create">
<p name="Active">1</p>
<p name="Type">CPU</p>
<p name="StDate">2013-07-27T00:00:00+00:00</p>
<p name="StpDate">2013-07-29T00:00:00+00:00</p>
</obj>
<obj class="E" version="1.0" distName="A-1/B-1/C-1/D-1/E-1" operation="NEW_create">
<p name="dayOfWeek">0</p>
<p name="interval">10</p>
</obj>
<obj class="D" version="1.0" distName="A-1/B-1/C-1/D-2" operation="delete">
<p name="Active">1</p>
<p name="Type">CPU</p>
<p name="StDate">2013-07-27T00:00:00+00:00</p>
<p name="StpDate">2013-07-29T00:00:00+00:00</p>
</obj><obj class="D" version="1.0" distName="A-1/B-1/C-1/D-2" operation="create">
<p name="Active">1</p>
<p name="Type">CPU</p>
<p name="StDate">2013-07-27T00:00:00+00:00</p>
<p name="StpDate">2013-07-29T00:00:00+00:00</p>
</obj>
<obj class="E" version="1.0" distName="A-1/B-1/C-1/D-2/E-1" operation="delete">
<p name="dayOfWeek">0</p>
<p name="interval">10</p>
</obj><obj class="E" version="1.0" distName="A-1/B-1/C-1/D-2/E-1" operation="create">
<p name="dayOfWeek">0</p>
<p name="interval">10</p>
</obj>
</Data>
</Object>

1 个答案:

答案 0 :(得分:0)

我可能会遗漏您的要求,但如果没有,那么更新只是删除和创建,可以在单个模板中完成。我将我的解决方案集中在行动上,而不是课堂上。我认为我的样式表会产生你要求制作的内容,但它可能不是你想做的。我希望它有所帮助。

t:\ftemp>type objects.xml 
<?xml version="1.0" encoding="UTF-8"?>
<Object>
<Data type="plan" name="testAom" id="10">

    <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-1" operation="create" >
        <p name="Active">1</p>
        <p name="Type">CPU</p>
        <p name="StDate">2013-07-27T00:00:00+00:00</p>
        <p name="StpDate">2013-07-29T00:00:00+00:00</p>
    </obj>

    <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-1/E-1" operation="create">
        <p name="dayOfWeek">0</p>
        <p name="interval">10</p>
    </obj>

    <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-2/E-1" operation="update">
        <p name="dayOfWeek">0</p>
        <p name="interval">10</p>
    </obj>

    <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-2" operation="update">
        <p name="Active">1</p>
        <p name="Type">CPU</p>
        <p name="StDate">2013-07-27T00:00:00+00:00</p>
        <p name="StpDate">2013-07-29T00:00:00+00:00</p>
    </obj>
</Data>
</Object>
t:\ftemp>call xslt objects.xml objects.xsl 
<?xml version="1.0" encoding="utf-8"?>
<Object>

   <Data type="plan" name="testAom" id="10">
      <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-1" operation="New_create">
         <p name="Active">1</p>
         <p name="Type">CPU</p>
         <p name="StDate">2013-07-27T00:00:00+00:00</p>
         <p name="StpDate">2013-07-29T00:00:00+00:00</p>
      </obj>
      <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-1/E-1" operation="New_create">
         <p name="dayOfWeek">0</p>
         <p name="interval">10</p>
      </obj>
      <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-2" operation="delete">
         <p name="Active">1</p>
         <p name="Type">CPU</p>
         <p name="StDate">2013-07-27T00:00:00+00:00</p>
         <p name="StpDate">2013-07-29T00:00:00+00:00</p>
      </obj>
      <obj class="D" version="1.0" distName="A-1/B-1/C-1/D-2" operation="create">
         <p name="Active">1</p>
         <p name="Type">CPU</p>
         <p name="StDate">2013-07-27T00:00:00+00:00</p>
         <p name="StpDate">2013-07-29T00:00:00+00:00</p>
      </obj>
      <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-2/E-1" operation="delete">
         <p name="dayOfWeek">0</p>
         <p name="interval">10</p>
      </obj>
      <obj class="E" version="1.0" distName="A-1/B-1/C-1/D-2/E-1" operation="create">
         <p name="dayOfWeek">0</p>
         <p name="interval">10</p>
      </obj>
   </Data>

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

<xsl:output indent="yes"/>

<xsl:template match="Object/Data">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <!--results are in distName order-->
    <xsl:apply-templates select="obj">
      <xsl:sort select="@distName"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<!--for creation, only the attribute changes, nothing else-->
<xsl:template match="obj[@operation='create']">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:attribute name="operation">New_create</xsl:attribute>
    <xsl:apply-templates select="*"/>
  </xsl:copy>
</xsl:template>

<!--remove those marked for deletion-->
<xsl:template match="obj[@operation='delete']"/>

<!--remove and recreate those marked for update-->
<xsl:template match="obj[@operation='update']">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:attribute name="operation">delete</xsl:attribute>
    <xsl:apply-templates select="*"/>
  </xsl:copy>
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:attribute name="operation">create</xsl:attribute>
    <xsl:apply-templates select="*"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="@*|node()"><!--identity for all other nodes-->
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rem Done!