如何使用xslt更改节点名称并将xml中该节点的数据复制到另一个节点

时间:2013-09-27 12:33:37

标签: xml xslt xslt-1.0

我的基础XML就像

<?xml version="1.0" encoding="iso-8859-1"?>
<Report version="1.0">
  <sourceName Identification="xyz"/>
  <sourcesys Identification="mycomp">
    <Manager>
      <ManagerNo>1023114455</ManagerNo>
      <Address>Delhi,India</Address>
      <Currency>
        <CurrencyType>Rupee</CurrencyType>
      </Currency>
    </Manager>
    <Manager>
      <ManagerNo>236784455</ManagerNo>
      <Address>California,USA</Address>
      <Currency>
        <CurrencyType>Dollar</CurrencyType>
      </Currency>
    </Manager>
  </sourcesys>
</Report>

我想将此XML转换为以下

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ManagerDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ManagerDetail>
    <ManagerNo>1023114455</ManagerNo>
    <Address>
      <PermenantAdd>California,USA</PermenantAdd>
    </Address>
    <CurrencyID>Rupee</CurrencyID>
  </ManagerDetail>
  <ManagerDetail>
    <ManagerNo>236784455</ManagerNo>
    <Address>
      <PermenantAdd>Delhi,India</PermenantAdd>
    </Address>
    <CurrencyID>Dollar</CurrencyID>
  </ManagerDetail>
</managerDetails>

以下是标签的映射:

  • sourcesys = managerDetails
  • 经理=经理详情
  • ManagerNo = ManagerNo
  • 地址= PermenantAdd
  • CurrencyType = CurrencyID

如何使用XSLT执行此操作?

2 个答案:

答案 0 :(得分:1)

试试这个:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" standalone="yes" encoding="utf-8" version="1.0"/>

  <xsl:template match="/">
    <xsl:element name="ManagerDetails">
      <xsl:apply-templates />
    </xsl:element>
  </xsl:template>

  <xsl:template match="/Report/sourcesys/Manager">
    <xsl:element name="ManagerDetail">
      <xsl:apply-templates />
    </xsl:element>
  </xsl:template>

  <xsl:template match="/Report/sourcesys/Manager/ManagerNo">
    <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="/Report/sourcesys/Manager/Address">
    <xsl:copy>
      <xsl:element name="PermenantAdd">
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/Report/sourcesys/Manager/Currency/CurrencyType">
    <xsl:element name="CurrencyID">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="text()"></xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

对于像这样的转换,你应该构建identity template,它本身复制你的XSLT中的所有节点

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

这意味着您只需要为要转换的节点编写模板(据说,这些都是 ManagerNo 元素)。

要转换 sourcesys (类似于经理),您可以执行此操作

<xsl:template match="sourcesys">
   <ManagerDetails>
      <xsl:apply-templates select="@*|node()"/>
   </ManagerDetails>
</xsl:template>

要删除元素,例如 sourceName ,您将拥有一个只忽略它的模板

<xsl:template match="sourceName"/>

要处理地址,这有点不同,因为您需要添加新元素。在这种情况下,我会编写一个与其文本节点匹配的模板,并在其中添加一个元素,如下所示:

<xsl:template match="Address/text()">
   <PermenantAdd>
      <xsl:value-of select="." />
   </PermenantAdd>
</xsl:template>

最后,对于 CurrencyType 进入 CurrencyID ,这很简单,但您还需要一个模板来跳过父货币元素,并处理它的孩子,如下:

<xsl:template match="Currency ">
   <xsl:apply-templates select="@*|node()"/>
</xsl:template>

试试这个XSLT

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

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

   <xsl:template match="/*">
        <xsl:apply-templates select="@*|node()"/>
   </xsl:template>

   <xsl:template match="sourcesys">
      <ManagerDetails>
         <xsl:apply-templates select="@*|node()"/>
      </ManagerDetails>
   </xsl:template>

   <xsl:template match="Manager">
      <ManagerDetail>
         <xsl:apply-templates select="@*|node()"/>
      </ManagerDetail>
   </xsl:template>

   <xsl:template match="sourceName"/>

   <xsl:template match="Address/text()">
      <PermenantAdd>
         <xsl:value-of select="." />
      </PermenantAdd>
   </xsl:template>

   <xsl:template match="Currency">
      <xsl:apply-templates select="@*|node()"/>
   </xsl:template>

   <xsl:template match="CurrencyType">
      <CurrencyID>
         <xsl:apply-templates select="@*|node()"/>
      </CurrencyID>
   </xsl:template>
</xsl:stylesheet>

另请注意,有一个模板<xsl:template match="/*">可以跳过根元素,如果它有一个名称空间也无关紧要。

编辑:如果您不想复制 sourcesys 的属性,而是使用新属性,请尝试更换模板

   <xsl:template match="sourcesys">
      <ManagerDetails href="...">
         <xsl:apply-templates select="node()"/>
      </ManagerDetails>
   </xsl:template>

请注意 xsl:apply-templates 现在缺少@*,因此不会复制任何其他属性。

如果你想要