XSLT映射元素复制文件

时间:2016-04-21 13:21:05

标签: xml xslt xslt-1.0

我想复制整个文件,通过将其映射到原始xml xsl文件中的相应元素来操纵它的一些元素。假设我有一个表告诉我file2中的哪些元素应该映射到file2中的相应元素。例如,file2中的元素编写器应该映射到file1中的元素作者。 为简洁起见,假设file1如下所示:

<?xml version="1.0" encoding="UTF-8"?>
    <Books>
      <book1>
        <title>Things fall apart</title>
        <author name = "Chinua Achebe" nationality = "Nigerian" />
      </book1>
    </Books>

file2看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
    <Books>
      <book2>
        <title> 1984</title>
        <writer>George Orwel</writer>
      </book2>
    </Books>

我有以下XSLT:

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

    <xsl:template match="Books">
      <Bundle>
        <id value="test"/>
        <resource>
          <!-- I am copying into here the entire File2 -->    
          <xsl:copy-of select="document('file2.xml')/*"/>      
        </resource>             
      </Bundle>
      <xsl:apply-templates/>
    </xsl:template>

现在,我知道我完全复制的file2中的元素编写器需要映射到file1中的相应元素,即author,这样最后只要元素编写器出现在file2中,就会改为:

<author name = "Chinua Achebe" nationality = "Nigerian" />

这应该是最终输出。

<Bundle>
    <id value="test"/>
    <resource>
      <?xml version="1.0" encoding="UTF-8"?>
  <!-- Here, the copied and modified file2-->  
        <Books>
            <book2>
                    <title> 1984</title>
                    <author name = "Chinua Achebe" nationality = "Nigerian" />
            </book2>
        </Books>

</resource>             
  </Bundle>

2 个答案:

答案 0 :(得分:0)

为什么不将file2.xml的内容放入变量?

示例(与您发布的特定文件无关):

<xsl:variable name="params">
    <xsl:copy-of select="doc('xslt_params.xml')"/>
</xsl:variable>

然后您可以访问整个文档中的任何内容。例如:

<xsl:variable name="lang">
    <xsl:value-of select="$params/descendant::param[1]/@lang1"/>
</xsl:variable>

答案 1 :(得分:0)

我不确定为什么你不能使用file2.xml作为转换的源XML - 或者为什么你甚至需要这里的file1.xml

在任何情况下,您都可以轻松地将模板应用于其他文档中的节点(或使用xsl:for-each)。这是一个例子:

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="*"/>

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

<xsl:template match="/">
    <Bundle>
        <id value="test"/>
        <resource>
            <xsl:apply-templates select="document('file2.xml')/*"/> 
        </resource>          
    </Bundle>
</xsl:template>

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

</xsl:stylesheet>

将此转换应用于任何格式正确的XML源时(请注意,您的file1.xml 格式正确),结果将为:

<?xml version="1.0" encoding="UTF-8"?>
<Bundle>
   <id value="test"/>
   <resource>
      <Books>
         <book2>
            <title> 1984</title>
            <author>George Orwel</author>
         </book2>
      </Books>
   </resource>
</Bundle>

请注意,这不是您问题中显示的结果。正如我在您的问题的评论中已经提到的,如果您想使用author中的整个file1.xml节点替代writer中的file2.xml节点,则需要提供样式表的逻辑,通过该逻辑,样式表可以识别哪个书的哪个属性用作替换。

例如,如果两个文件只有一个Book,您可以使用:

<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="*"/>

<xsl:variable name="input" select="/" />

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

<xsl:template match="/">
    <Bundle>
        <id value="test"/>
        <resource>
            <xsl:apply-templates select="document('file2.xml')/*"/> 
        </resource>          
    </Bundle>
</xsl:template>

<xsl:template match="writer">
    <xsl:copy-of select="$input/Books/book1/author"/>
</xsl:template>

</xsl:stylesheet>

给出格式良好的输入,例如:

<强> XML

<Books>
    <book1>
        <title>Things fall apart</title>
        <author name = "Chinua Achebe" nationality = "Nigerian"></author>
    </book1>
</Books>

这将返回:

<?xml version="1.0" encoding="UTF-8"?>
<Bundle>
   <id value="test"/>
   <resource>
      <Books>
         <book2>
            <title> 1984</title>
            <author name="Chinua Achebe" nationality="Nigerian"/>
         </book2>
      </Books>
   </resource>
</Bundle>