xml xslt转换

时间:2011-09-26 15:28:07

标签: xml xslt

我一直在尝试使用XSLT将一些简单的XML转换为另一个简单的XML。我是XSLT的新手,所以如果有人能给我一个例子,我会扩展它。

我有任意XML文件:例如

<element>
 <child_element>
  <grandchild_element>
     only one
  </grandchild_element>
 </child_element>
 <child_element>
  <grandchild_element>
     one
  </grandchild_element>
  <grandchild_element>
     two
  </grandchild_element>
 </child_element>
</element>

我想从中制作:

<tree>
 <item class="element" id="1">
  <item class="child_element" id="11">
   <item class="grandchild_element" id="111" value="only one"/>
  </item>
  <item class="child_element" id="12">
   <item class="grandchild_element" id="121" value="only one"/>
   <item class="grandchild_element" id="122" value="only one"/>
  </item>
 </item>
</tree>

谢谢!

3 个答案:

答案 0 :(得分:0)

您要为每个元素编写一个模板,例如:

<xsl:template match="child_element">

并使用前面或前面的兄弟元素的计数来获取“id”字段:

<xsl:template match="child_element">
    <item>
        <xsl:attribute name="id">
            <xsl:value-of select="concat(count(preceding-sibling::element),count(preceding::child_element)+1)"/>
        </xsl:attribute>
    </item>
</xsl:template>

对于孙子女来说,你将不得不玩..和兄弟姐妹。 但是我强烈建议你不要将你当前的计数方案用于id:一旦你在任何级别有10个以上的节点,就会发生碰撞。

答案 1 :(得分:0)

要获得每个元素的 id ,您需要回顾每个祖先,并为每个级别计算前一个兄弟的数量。

<xsl:attribute name="id">
    <xsl:apply-templates select="ancestor-or-self::*" mode="id"/>
</xsl:attribute>

<xsl:template match="*" mode="id">
   <xsl:value-of select="count(preceding-sibling::*) + 1"/>
</xsl:template>

要将元素名称转换为属性是直截了当的,请执行以下操作:

<xsl:attribute name="class">
   <xsl:value-of select="local-name()"/>
</xsl:attribute>

将文本转换为属性也非常简单。

<xsl:template match="text()">
   <xsl:attribute name="value">
      <xsl:value-of select="normalize-space(.)"/>
   </xsl:attribute>
</xsl:template>

这里的 normalize-space 是删除示例XML中显示的换行符。

这是完整的XSLT

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

   <!-- Match root element -->
   <xsl:template match="/">
      <tree>
         <xsl:apply-templates select="node()"/>
      </tree>
   </xsl:template>

   <!-- Match any element in the XML -->
   <xsl:template match="*">
      <item>
         <xsl:attribute name="id">
            <xsl:apply-templates select="ancestor-or-self::*" mode="id"/>
         </xsl:attribute>
         <xsl:attribute name="class">
            <xsl:value-of select="local-name()"/>
         </xsl:attribute>
         <xsl:apply-templates select="@*|node()"/>
      </item>
   </xsl:template>

   <!-- Used to match ancestors to work out the id -->
   <xsl:template match="*" mode="id">
      <xsl:value-of select="count(preceding-sibling::*) + 1"/>
   </xsl:template>

   <!-- Convert text into the value attribute -->
   <xsl:template match="text()">
      <xsl:attribute name="value">
         <xsl:value-of select="normalize-space(.)"/>
      </xsl:attribute>
   </xsl:template>

   <!-- Copy any existing attributes in the XML -->
   <xsl:template match="@*">
      <xsl:copy/>
   </xsl:template>
</xsl:stylesheet>

当应用于您的示例XML时,将输出以下内容:

<tree>
   <item id="1" class="element">
      <item id="11" class="child_element">
         <item id="111" class="grandchild_element" value="only one"/>
      </item>
      <item id="12" class="child_element">
         <item id="121" class="grandchild_element" value="one"/>
         <item id="122" class="grandchild_element" value="two"/>
      </item>
   </item>
</tree>

答案 2 :(得分:0)

最简单/最短的解决方案之一(只有3个模板,没有模式,没有轴,没有count(),只有一个xsl:attribute)同时也是最通用的(与之配合使用)任何元素名称)

<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="/">
  <tree>
   <xsl:apply-templates/>
  </tree>
 </xsl:template>

 <xsl:template match="*">
  <xsl:variable name="vNumber">
   <xsl:number count="*" level="multiple"/>
  </xsl:variable>

  <item class="{name()}"
        id="{translate($vNumber, '.', '')}">
   <xsl:apply-templates/>
  </item>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:attribute name="value">
   <xsl:value-of select="normalize-space()"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<element>
 <child_element>
  <grandchild_element>
     only one
  </grandchild_element>
 </child_element>
 <child_element>
  <grandchild_element>
     one
  </grandchild_element>
  <grandchild_element>
     two
  </grandchild_element>
 </child_element>
</element>

产生了想要的正确结果

<tree>
   <item class="element" id="1">
      <item class="child_element" id="11">
         <item class="grandchild_element" id="111" value="only one"/>
      </item>
      <item class="child_element" id="12">
         <item class="grandchild_element" id="121" value="one"/>
         <item class="grandchild_element" id="122" value="two"/>
      </item>
   </item>
</tree>