用于将属性转换为子元素并将当前元素的值放入其另一个新子元素的XSLT代码

时间:2015-04-21 09:13:02

标签: xslt-1.0

我不知道XSLT,请帮忙: 我有以下XML:

<OLifE>
  <Holding id="1234">
    <HoldingKey>1397650618090</HoldingKey>
    <HoldingTypeCode tc="2">Policy</HoldingTypeCode>
    <HoldingStatus tc="2">Inactive</HoldingStatus>
    <CarrierAdminSystem>PAS</CarrierAdminSystem>
  </Holding>
</OLifE>

我希望输出如下:

<OLifE>
  <Holding>
    <id>1234</id>
    <HoldingKey>1397650618090</HoldingKey>
    <HoldingTypeCode>
      <tc>2</tc>
      <value>Policy</value>
    </HoldingTypeCode>
    <HoldingStatus>
      <tc>2</tc>
      <value>Inactive</value>
    </HoldingStatus>
    <CarrierAdminSystem>PAS</CarrierAdminSystem>
   </Holding>
 </OLifE>

请注意,所有属性都需要转换为子元素,但对于指定了tc属性的元素:

<HoldingTypeCode tc="2">Policy</HoldingTypeCode>

需要小心处理。

我不希望输出如下:

<HoldingTypeCode>
                <tc>2</tc>Policy</HoldingTypeCode>

我有以下需要稍作修改的XSLT代码:

<?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="@*">
                 <xsl:element name="{name()}">
                       <xsl:value-of select="."/>
                 </xsl:element>
            </xsl:for-each>
            <xsl:apply-templates select="*|text()"/>
       </xsl:element>
 </xsl:template>

请帮忙。

2 个答案:

答案 0 :(得分:1)

假设您需要通用解决方案,那么:

XSLT 1.0

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

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

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

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

</xsl:stylesheet>

修改

  

但是,我原始XML中的根元素有xmlns =“some web   地址“属性。

在这种情况下,请将第一个模板更改为:

<!-- modified identity transform -->
<xsl:template match="*">
     <xsl:element name="{name()}">
        <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
</xsl:template>

这假设您希望所有输出节点都不在命名空间中。

答案 1 :(得分:0)

我认为您可以在要输出属性的地方定义这样的模板:

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

对于最常见的情况,您使用与以前几乎相同的模板,只需为属性调用新模板:

<xsl:template match="*">
   <xsl:element name="{name()}">
      <xsl:call-template name="transform.attrs">
      <xsl:apply-templates select="*|text()"/>
   </xsl:element>
</xsl:template>

对于具体元素,带有@tc属性:

<xsl:template match="*[@tc]">
  <xsl:element name="{name()}">
    <xsl:call-template name="transform.attrs" />
    <value>
       <xsl:apply-templates select="*|text()"/>
    </value>
  </xsl:element>
</xsl:template>