XML使用XSLT进行自定义转换

时间:2017-04-12 15:25:08

标签: xml xslt xpath

我输入了XML,

<?xml version="1.0" encoding="UTF-8"?>
<Vehicle>
<Ordinary>
    <Car>Honda City</Car>
</Ordinary> 
<Luxury>
    <Car>Volkswagon</Car>
</Luxury>   
<Luxury>
    <Car>Dzire</Car>
</Luxury>

我必须使用XSLT将此xml消息转换为

<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<title>/Vehicle/Ordinary/</title>
<text>Car</text>
<answer>Honda City</answer>
</item>
<item>
<id>2</id>
<title>/Vehicle/Luxury[1]/</title>
<text>Car</text>
<answer>Volkswagon</answer>
</item>
<item>
<id>3</id>
<title>/Vehicle/Luxury[2]/</title>
<text>Car</text>
<answer>Dzire</answer>
</item>

  • 此处id可以是自动生成的唯一编号..
  • 所有没有任何值的父标签Xpath都会进入&lt; title&gt;标签。
  • 有价值的元素进入&lt; text&gt;标签
  • 实际价值来自&lt; answer&gt;标签
  • XSLT应该足够通用,可以应用任何格式的XML文档&amp;不具体到给定的样本xml。

我从下面开始,

<?xml version="1.0" encoding="windows-1252" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:strip-space elements = "*" />
<xsl:template match="/">
<items>
<xsl:apply-templates/>
</items>
</xsl:template>
<xsl:template match="text()">
<item>      
<title>
<xsl:for-each select="ancestor-or-self::*">
<xsl:text>/</xsl:text>
<xsl:value-of select="name()" />
</xsl:for-each>
</title>    
<answer>
<xsl:value-of select="." />
<xsl:apply-templates/>
</answer>
</item>
</xsl:template>
</xsl:stylesheet>    

它生成以下输出,

<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<title>/Vehicle/Ordinary/Car</title>
<answer>Honda City</answer>
</item>
<item>
<id>2</id>
<title>/Vehicle/Luxury[1]/Car</title>   
<answer>Volkswagon</answer>
</item>
<item>
<id>2</id>
<title>/Vehicle/Luxury[2]/Car</title>   
<answer>Dzire</answer>
</item>
</items>    

需要你的帮助......

1 个答案:

答案 0 :(得分:0)

  

这里的id可以是自动生成的唯一编号..

我使用generate-id()获取唯一ID。

  

所有没有任何值的父标签Xpath都会进入   <title>代码。

根据你的目标输出,看起来你想要除了第一个之外的祖先。

  

具有值的元素位于<text>标记内。

只需使用父级的name()

  

实际值来自<answer>标记。

看起来你已经覆盖了它。

示例...

XSLT 1.0

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

  <xsl:template match="/">
    <items>
      <xsl:apply-templates/>
    </items>
  </xsl:template>

  <xsl:template match="text()">
    <item>
      <id><xsl:value-of select="generate-id()"/></id>
      <title>
        <xsl:for-each select="ancestor::*[position()>1]">
          <xsl:value-of select="concat('/',name())"/>
          <xsl:if test="(preceding-sibling::*|
            following-sibling::*)[name()=name(current())]">
            <xsl:value-of select="concat('[',
              count(preceding-sibling::*[name()=name(current())])+1,
              ']')"/>
          </xsl:if>
        </xsl:for-each>
        <xsl:text>/</xsl:text>
      </title>
      <text><xsl:value-of select="name(..)"/></text>
      <answer>
        <xsl:value-of select="." />
        <xsl:apply-templates/>
      </answer>
    </item>
  </xsl:template>
</xsl:stylesheet>

<强>输出

<items>
   <item>
      <id>d0t4</id>
      <title>/Vehicle/Ordinary/</title>
      <text>Car</text>
      <answer>Honda City</answer>
   </item>
   <item>
      <id>d0t7</id>
      <title>/Vehicle/Luxury[1]/</title>
      <text>Car</text>
      <answer>Volkswagon</answer>
   </item>
   <item>
      <id>d0t10</id>
      <title>/Vehicle/Luxury[2]/</title>
      <text>Car</text>
      <answer>Dzire</answer>
   </item>
</items>