使用XSLT将节点移动/复制到多个子节点

时间:2010-12-01 09:41:47

标签: xml xslt copy

我是XSLT的新手,需要一些帮助来解决我的一个问题。我想要完成的是:

我有一个类似这样的文件:

<Transaction>
    <Date>2010-10-14T12:06:12.164+01:00</Date>
    <Production>NO</Production>
    <Document fun:OID="1.9.101106">
        <DocumentType xmlns="">Monthly A</DocumentType>
        <RangeName xmlns="">Range Name</RangeName>
        <Name xmlns="">Equity</Name>
        <Language xmlns="">English</Language>
        <Class xmlns="">A Acc</Class>
        <Active xmlns="">YES</Active>
        <Country xmlns="">UK</Country>
        <Country xmlns="">Luxembourg</Country>
        <Country xmlns="">Denmark</Country>
        <Country xmlns="">Malta</Country>
        <Primary fun1:OID="1.9.101106" xmlns="" xmlns:fun1="DocumentXML.com">
              <Name>SISF-Indian-Equity-A-Acc-FMR-UKEN</Name>
              <FileSizeInKB>176784</FileSizeInKB>
              <FileType>pdf</FileType>
              <ReportingPeriod>September</ReportingPeriod>
              <ReportingYear>2010</ReportingYear>
        </Primary>
        <Primary fun1:OID="1.9.101118" xmlns="" xmlns:fun1="DocumentXML.com">
              <Name>SISF-Indian-Equity-A-Acc</Name>
              <FileSizeInKB>176784</FileSizeInKB>
              <FileType>pdf</FileType>
              <ReportingPeriod>September</ReportingPeriod>
              <ReportingYear>2010</ReportingYear>
        </Primary>
    </Document>
</Transaction>

我想保留当前文件,除了我想要将国家/地区节点复制到主节点中。所以它看起来像这样:

<Transaction>
    <Date>2010-10-14T12:06:12.164+01:00</Date>
    <Production>NO</Production>
    <Document fun:OID="1.9.101106">
        <DocumentType xmlns="">Monthly A</DocumentType>
        <RangeName xmlns="">Range Name</RangeName>
        <Name xmlns="">Equity</Name>
        <Language xmlns="">English</Language>
        <Class xmlns="">A Acc</Class>
        <Active xmlns="">YES</Active>
        <Country xmlns="">UK</Country>
        <Country xmlns="">Luxembourg</Country>
        <Country xmlns="">Denmark</Country>
        <Country xmlns="">Malta</Country>
        <Primary fun1:OID="1.9.101106" xmlns="" xmlns:fun1="DocumentXML.com">
              <Name>SISF-Indian-Equity-A-Acc-FMR-UKEN</Name>
              <FileSizeInKB>176784</FileSizeInKB>
              <FileType>pdf</FileType>
              <ReportingPeriod>September</ReportingPeriod>
              <ReportingYear>2010</ReportingYear>
              <Country xmlns="">UK</Country>
              <Country xmlns="">Luxembourg</Country>
              <Country xmlns="">Denmark</Country>
              <Country xmlns="">Malta</Country>
        </Primary>
        <Primary fun1:OID="1.9.101118" xmlns="" xmlns:fun1="DocumentXML.com">
              <Name>SISF-Indian-Equity-A-Acc</Name>
              <FileSizeInKB>176784</FileSizeInKB>
              <FileType>pdf</FileType>
              <ReportingPeriod>September</ReportingPeriod>
              <ReportingYear>2010</ReportingYear>
              <Country xmlns="">UK</Country>
              <Country xmlns="">Luxembourg</Country>
              <Country xmlns="">Denmark</Country>
              <Country xmlns="">Malta</Country>
        </Primary>
    </Document>
</Transaction>

实现这一目标的最佳方法是什么?我是否需要先复印整份文件,然后复制各个国家,或者我可以一次性完成这项工作吗?

3 个答案:

答案 0 :(得分:2)

诀窍是使用identity template复制整个文档,但仍然可以修改所需的部分:

使用此(稍加修改)输入:

<?xml version="1.0" encoding="UTF-8"?>
<Transaction xmlns:fun1="DocumentXML.com">
  <Date>2010-10-14T12:06:12.164+01:00</Date>
  <Production>NO</Production>
  <Document fun1:OID="1.9.101106">
    <DocumentType xmlns="">Monthly A</DocumentType>
    <RangeName xmlns="">Range Name</RangeName>
    <Name xmlns="">Equity</Name>
    <Language xmlns="">English</Language>
    <Class xmlns="">A Acc</Class>
    <Active xmlns="">YES</Active>
    <Country xmlns="">UK</Country>
    <Country xmlns="">Luxembourg</Country>
    <Country xmlns="">Denmark</Country>
    <Country xmlns="">Malta</Country>
    <Primary fun1:OID="1.9.101106" xmlns="" xmlns:fun1="DocumentXML.com">
      <Name>SISF-Indian-Equity-A-Acc-FMR-UKEN</Name>
      <FileSizeInKB>176784</FileSizeInKB>
      <FileType>pdf</FileType>
      <ReportingPeriod>September</ReportingPeriod>
      <ReportingYear>2010</ReportingYear>
    </Primary>
    <Primary fun1:OID="1.9.101118" xmlns="" xmlns:fun1="DocumentXML.com">
      <Name>SISF-Indian-Equity-A-Acc</Name>
      <FileSizeInKB>176784</FileSizeInKB>
      <FileType>pdf</FileType>
      <ReportingPeriod>September</ReportingPeriod>
      <ReportingYear>2010</ReportingYear>
    </Primary>
  </Document>
</Transaction>

输入XML更改的说明:提供的输入XML无效,因为您对每个属性都使用双引号。此外,未为fun节点声明Document前缀。我已将fun前缀更改为fun1并将前缀绑定在根级别。


此样式表:

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

  <xsl:output indent="yes"/>

  <!-- This identity template copies the document -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>

  <!-- This template will only match the 'Primary' nodes
       and modify them the way you want. -->
  <xsl:template match="Primary">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
      <!-- As you can see, this is the only difference
           between the identity template and this specific
           template. -->
      <xsl:copy-of select="../Country"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

将为您提供相同的文档,但将Country复制到Primary

<?xml version="1.0" encoding="UTF-8"?>
<Transaction xmlns:fun1="DocumentXML.com">
  <Date>2010-10-14T12:06:12.164+01:00</Date>
  <Production>NO</Production>
  <Document fun1:OID="1.9.101106">
      <DocumentType>Monthly A</DocumentType>
      <RangeName>Range Name</RangeName>
      <Name>Equity</Name>
      <Language>English</Language>
      <Class>A Acc</Class>
      <Active>YES</Active>
      <Country>UK</Country>
      <Country>Luxembourg</Country>
      <Country>Denmark</Country>
      <Country>Malta</Country>
      <Primary fun1:OID="1.9.101106">
         <Name>SISF-Indian-Equity-A-Acc-FMR-UKEN</Name>
         <FileSizeInKB>176784</FileSizeInKB>
         <FileType>pdf</FileType>
         <ReportingPeriod>September</ReportingPeriod>
         <ReportingYear>2010</ReportingYear>
         <Country>UK</Country>
         <Country>Luxembourg</Country>
         <Country>Denmark</Country>
         <Country>Malta</Country>
      </Primary>
      <Primary fun1:OID="1.9.101118">
         <Name>SISF-Indian-Equity-A-Acc</Name>
         <FileSizeInKB>176784</FileSizeInKB>
         <FileType>pdf</FileType>
         <ReportingPeriod>September</ReportingPeriod>
         <ReportingYear>2010</ReportingYear>
         <Country>UK</Country>
         <Country>Luxembourg</Country>
         <Country>Denmark</Country>
         <Country>Malta</Country>
      </Primary>
  </Document>
</Transaction>

答案 1 :(得分:1)

只是为了好玩,最短的样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
            <xsl:apply-templates select="self::Primary/../Country"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

其他较短而不改变身份规则:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Primary/*[last()]">
        <xsl:call-template name="identity"/>
        <xsl:apply-templates select="../../Country"/>
    </xsl:template>
</xsl:stylesheet>

注意:两者都不使用xsl:copy-of,而是使用xsl:apply-templates。这允许进一步处理。

答案 2 :(得分:0)

如果你使用xslt来生成一个新的xml doccument,我会创建一个doccument然后为主节点做这个

<xsl:for-each select="../Country">
<Country><xsl:value-of select="."/></Country>
</xsl:for-each>

可能有更简单的方法来实现相同的结果..?