2011-05-16 109 views
5

所以我想下面使用XSL使用XSL移动从一个节点到另一个

<doc> 
    <data id="priority" level="2" include="true"> 
     <name>Priority</name> 
    </data> 
    <data id="cost" level="1" leveltype="number"> 
     <name>Cost</name> 
    </data> 
    <data id="date" level="3" include="true"> 
     <name>Date</name> 
    </data> 
</doc> 

转换为该

<doc> 
    <data id="priority"> 
     <name>Priority</name> 
    </data> 
    <data id="cost"> 
     <name>Cost</name> 
    </data> 
    <data id="date"> 
     <name>Date</name> 
    </data> 

    <!-- ordering matters, though if necessary I can reorder this manually via the DOM instead of XSL --> 
    <levels> 
     <level id="cost" include="false" type="number"/> 
     <level id="priority" include="true"/> 
     <level id="date" include="true"/> 
    </level> 
</doc> 

基本上,我想借此级别的属性,让他们自己事情。如果有某种方法可以删除级别号码并使用节点的顺序来代表这一点,那么将会带来巨大的好处。

+0

我看不到任何东西...... – 2011-05-16 19:12:28

+0

如果您可以添加样本以及最终结果的样本,那将有助于我们帮助您。 – 2011-05-16 19:12:57

+0

好问题,+1。看到我的答案是一个完整的,简短的,基于模板的解决方案 - 这可能是所有答案中最短,最简单和最容易扩展的。 – 2011-05-17 13:40:47

回答

0

这里的解决方案:

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

    <!-- attribute suppression template --> 
    <xsl:template match="@*" priority="2"/> 

    <xsl:template match="/doc"> 
    <xsl:copy> 
     <xsl:apply-templates select="*" mode="data"/> 
     <levels> 
     <xsl:apply-templates select="*" mode="levels"> 
      <xsl:sort select="@level" data-type="number"/> 
     </xsl:apply-templates> 
     </levels> 
    </xsl:copy> 
    </xsl:template> 


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

    <xsl:template match="@*" mode="data"/><!-- suppress --> 
    <xsl:template match="@id" mode="data" priority="2"><!-- keep --> 
    <xsl:copy-of select="."/></xsl:template> 


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

    <xsl:template match="data" mode="levels"> 
    <level> 
     <xsl:apply-templates select="@*" mode="levels"/> 
    </level></xsl:template> 

    <xsl:template match="@level" mode="levels"/><!-- suppress --> 
    <xsl:template match="@leveltype" mode="levels"><!-- rename --> 
    <xsl:attribute name="type"><xsl:value-of select="."/> 
    </xsl:attribute></xsl:template> 

</xsl:stylesheet> 

我认为<level id="cost" include="false" type="number"/>在你的预期输出是复制/粘贴人工制品作为属性从level[@id="cost"]输入丢失。

0

可能是一个简单的方法:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:template match="/"> 
    <doc> 
     <xsl:for-each select="doc/data"> 
      <data> 
       <xsl:attribute name="id"> 
        <xsl:value-of select="@id"/> 
       </xsl:attribute> 
       <name><xsl:value-of select="name" /></name> 
      </data> 
     </xsl:for-each> 
     <levels> 
      <xsl:for-each select="doc/data"> 
       <xsl:sort select="@level" /> 
       <level> 
        <xsl:attribute name="id"> 
         <xsl:value-of select="@id"/> 
        </xsl:attribute> 
        <xsl:choose> 
         <xsl:when test="@include='true'"> 
          <xsl:attribute name="include">true</xsl:attribute> 
         </xsl:when> 
         <xsl:otherwise> 
          <xsl:attribute name="include">false</xsl:attribute> 
         </xsl:otherwise> 
        </xsl:choose> 
       </level> 
      </xsl:for-each> 
     </levels> 
    </doc> 
</xsl:template> 
</xsl:stylesheet> 
2

只是一个变种:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="doc"> 

<doc> 

    <!-- build and sort data nodes --> 
    <xsl:for-each select="data"> 
    <xsl:sort select="@id"/> 
    <data id="{@id}"> 
    <xsl:copy-of select="name"/> 
    </data> 
    </xsl:for-each> 

    <!-- build and sort levels --> 
    <levels> 
    <xsl:for-each select="data"> 
    <xsl:sort select="@id"/> 
     <level id="{@id}" include="{boolean(@include)}"> 
     <xsl:if test="@leveltype"> 
     <xsl:attribute name="type"> 
     <xsl:value-of select="@leveltype"/> 
     </xsl:attribute> 
     </xsl:if> 
     </level> 
    </xsl:for-each> 
    </levels> 

</doc> 

</xsl:template> 
</xsl:stylesheet> 
+0

很好的实施。 – Mic 2011-05-17 07:36:42

3

这仅仅是使用更短和更简单的解决方案模板(无<xsl:for-each>):

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

<xsl:template match="/*"> 
    <doc> 
    <xsl:apply-templates select="*"/> 
    <levels> 
    <xsl:apply-templates select="data" mode="level"> 
    <xsl:sort select="@level" data-type="number"/> 
    </xsl:apply-templates> 
    </levels> 
    </doc> 
</xsl:template> 
<xsl:template match="data/@*[not(name()='id')]"/> 

<xsl:template match="data" mode="level"> 
    <level id="{@id}" include="{boolean(@include)}"> 
    <xsl:if test="@leveltype"> 
    <xsl:attribute name="type"><xsl:value-of select="@leveltype"/></xsl:attribute> 
    </xsl:if> 
    </level> 
</xsl:template> 
</xsl:stylesheet> 

当应用o n中提供XML文档

<doc> 
    <data id="priority" level="2" include="true"> 
     <name>Priority</name> 
    </data> 
    <data id="cost" level="1" leveltype="number"> 
     <name>Cost</name> 
    </data> 
    <data id="date" level="3" include="true"> 
     <name>Date</name> 
    </data> 
</doc> 

想要的,正确的结果产生

<doc> 
    <data id="priority"> 
     <name>Priority</name> 
    </data> 
    <data id="cost"> 
     <name>Cost</name> 
    </data> 
    <data id="date"> 
     <name>Date</name> 
    </data> 
    <levels> 
     <level id="cost" include="false" type="number"/> 
     <level id="priority" include="true"/> 
     <level id="date" include="true"/> 
    </levels> 
</doc> 

说明

  1. 使用并重写身份规则/模板。使用mode="level"生成结果文档的第二部分。

+0

+1。我徘徊了一段时间没有'xsl:for-each'的解决方案。 – 2011-05-17 21:20:18

+1

@empo:谢谢:仅当需要将当前文档更改为另一个文档时,才使用''(几乎),这样'key()'函数才能与第二个文件。除了这个用例外,我不认为还有其他需要''的情况。 – 2011-05-17 21:28:45

+0

听起来很简单!我将在下次考虑使用循环。 – 2011-05-17 21:39:29

相关问题