【问题标题】:Order of nodes in XSL TransformationXSL 转换中的节点顺序
【发布时间】:2013-08-05 14:57:38
【问题描述】:

我有一个如下所示的 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>

这里当操作属性为"update"时,我需要进行删除和创建。

上面的节点有一个基于属性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>

【问题讨论】:

  • 您给了我们一个无效的样式表及其不希望的结果,但您没有向我们展示您给定的示例输入的理想结果是什么。
  • 嗨,Ken,我已经更正了我的问题并更新了所需的理想结果..
  • 你需要处理A、B、C的类属性吗?
  • 是的....可以有任何类...

标签: xslt xslt-1.0


【解决方案1】:

我可能在您的要求中遗漏了某些内容,但如果没有,那么更新只是删除和创建,并且可以在单个模板中完成。我的解决方案集中在行动上,而不是课堂上。我认为我的样式表完全符合您的要求,但它可能没有按照您的意愿进行。希望对你有帮助。

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! 

【讨论】:

  • 嗨,Ken,如果 xml 与 xmlns="xyz.xsd" 相关联,如何处理上述 xsl .. 那时我不知道如何使用它?
  • 这与将任何命名空间附加到输入元素没有什么不同,只需使用通常的方法在样式表中的元素名称中添加命名空间前缀即可。
猜你喜欢
  • 2015-05-11
  • 1970-01-01
  • 1970-01-01
  • 2018-03-25
  • 1970-01-01
  • 2022-01-22
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多