使用XSLT将XML属性转换为元素

时间:2018-04-12 13:42:26

标签: xml xslt

我正在尝试使用以下样式表将输入XML文档属性转换为元素:

/en/?lang=en

然而,尽管基于每个元素属性正确地创建了新元素,但“leaf”元素(即没有子元素)将其文本与创建的元素混合。 E.g。

输入XML

<?xml version="1.0"?>
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="xml"/>
      <xsl:template match="*">
        <xsl:element name="{name()}">
          <xsl:for-each select="@*[name()!='type']">
            <xsl:element name="{name()}">
              <xsl:value-of select="."/>
            </xsl:element>
          </xsl:for-each>
          <xsl:apply-templates select="*|text()"/>
        </xsl:element>
      </xsl:template>
      </xsl:stylesheet>

输出XML

<order>
  <id>12345</id>
  <date>Today</date>
  <location country="PT">LX</location>
  <location country="ES">Barcelona</location>
  <items type="array" stock="true">
    <item>
      <id type="array">item1</id>
      <spec>
        <color type="array">brown</color>
        <price currency="euro">20</price>
        <usage>office</usage>
        <usage>home</usage>
      </spec>
    </item>
  </items>
</order>

我想要什么

<order>
  <id>12345</id>
  <date>Today</date>
  <location>
    <country>PT</country>LX
  </location>
  <location>
    <country>ES</country>Barcelona
  </location>
  <items>
    <stock>true</stock>
    <item>
      <id>item1</id>
      <spec>
        <color>brown</color>
        <price>
          <currency>euro</currency>20
        </price>
        <usage>office</usage>
        <usage>home</usage>
      </spec>
    </item>
  </items>
</order>

我尝试了什么

    ...
<location>
    <text>LX</text>
    <country>PT</country>
  </location>
  <location>
    <text>Barcelona</text>
    <country>ES</country>
  </location>
...
        <price>
          <text>20</text>
          <currency>euro</currency>
        </price>
       ...

问题 尽管正确创建了新元素标签

<?xml version="1.0"?>
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="xml"/>
      <xsl:template match="*">
        <xsl:element name="{name()}">
          <xsl:for-each select="@*[name()!='type']">
            <xsl:element name="text">
              <xsl:value-of select=".."/>
            </xsl:element>
            <xsl:element name="{name()}">
               <xsl:value-of select="."/>
             </xsl:element>
          </xsl:for-each>
          <xsl:apply-templates select="*|text()"/>
        </xsl:element>
      </xsl:template>
      </xsl:stylesheet>

它还在“非叶子”元素(即带有子元素的元素)上创建“text”元素,获取提供的示例:

  <text>20</text>

我不想要

...
<items>
    <text>item1brown20officehome</text>
    <stock>true</stock>
    <item>
      <id>item1</id>
      <spec>
        <color>brown</color>
        <price>
          <text>20</text>
          <currency>euro</currency>20
        </price>
        <usage>office</usage>
        <usage>home</usage>
      </spec>
    </item>
  </items>
...

有什么想法吗?提前谢谢。

1 个答案:

答案 0 :(得分:1)

我不确定这是否会创建您想要的确切输出,因为您只包含了所需输出的一部分,但尝试这样的事情......

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

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

  <xsl:template match="*[@*]/text()">
    <text><xsl:value-of select="."/></text>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:element name="{name()}">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

小提琴:http://xsltfiddle.liberty-development.net/jyH9rLX

  

如果我只想保留名称为&#34; type&#34;如   属性(不将它们转换为元素,而是将它们保存为元素   最初)。我怎么能实现这样的目标呢?

更新了XSLT

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

  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates select="@type|text()"/>
      <xsl:apply-templates 
        select="@*[not(name()='type')]|*|comment()|processing-instruction()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[@*]/text()">
    <text><xsl:value-of select="."/></text>
  </xsl:template>

  <xsl:template match="@type">
    <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:element name="{name()}">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

更新了小提琴:http://xsltfiddle.liberty-development.net/jyH9rLX/2