XSLT模板和覆盖

时间:2015-01-23 04:13:45

标签: xslt

我有一个系统,我想要一个基本文件和几个可能的“模板”snippit类型文件。以下是一个例子:

<BookClub ref="WashingtonClub101">
    <ReadingList ref="SummerReadingList">
        <Book>
            <Id>GUID1</Id>
            <Name>Favorite Book</Name>
            <Author>Favorite Author</Author>
            <Cost>$12.00</Cost>
        </Book>
        <Book>
            <Id>GUID2</Id>
            <Name>Boring Book</Name>
            <Author>Fun Author</Author>
            <Cost>$30.00</Cost>
        </Book>
        <Book>
            <Id>GUID4</Id>
            <Name>Summer Book 7</Name>
        </Book>
        <Remove Id="GUID5" />
    </ReadingList>
</BookClub>

<ReadingList Id="SummerReadingList">
    <Book>
        <Id>GUID3</Id>
        <Name>Summer Book 1</Name>
        <Author>Favorite Author</Author>
        <Cost>$40.00</Cost>
    </Book>
    <Book>
        <Id>GUID4</Id>
        <Name>Summer Book 2</Name>
        <Author>Favorite Author</Author>
        <Cost>$40.00</Cost>
    </Book>
    <Book>
        <Id>GUID5</Id>
        <Name>Summer Book 3</Name>
        <Author>Favorite Author</Author>
        <Cost>$40.00</Cost>
    </Book>
</ReadlingList>

<BookClub Id="WashingtonClub101">
    <ReadingList>
        <Book>
            <Id>GUID101</Id>
            <Name>Washington Club Book</Name>
            <Author>Mr. Book</Author>
            <Cost>$18.00</Cost>
        </Book>
    </ReadingList>
    <Location>
        <Name>Seattle Public Library</Name>
    </Location>
</BookClub>

第一个BookClub是基础,如果引用(通过参考)snippits。预期的产出低于,但我根本不关心订单。

<BookClub>
    <ReadingList>
        <Book>
            <Id>GUID1</Id>
            <Name>Favorite Book</Name>
            <Author>Favorite Author</Author>
            <Cost>$12.00</Cost>
        </Book>
        <Book>
            <Id>GUID2</Id>
            <Name>Boring Book</Name>
            <Author>Fun Author</Author>
            <Cost>$30.00</Cost>
        </Book>
        <Book>
            <Id>GUID3</Id>
            <Name>Summer Book 1</Name>
            <Author>Favorite Author</Author>
            <Cost>$40.00</Cost>
        </Book>
        <Book>
            <Id>GUID4</Id>
            <Name>Summer Book 7</Name>
            <Author>Favorite Author</Author>
            <Cost>$40.00</Cost>
        </Book>
        <Book>
            <Id>GUID101</Id>
            <Name>Washington Club Book</Name>
            <Author>Mr. Book</Author>
            <Cost>$18.00</Cost>
        </Book>
    </ReadingList>
    <Location>
        <Name>Seattle Public Library</Name>
    </Location>
</BookClub>

基本上,我希望基础与snippit合并,基础是碰撞时的覆盖。理想情况下,我不必指定合并的每个节点(我的实际问题空间有更多标签)。真实系统中的ID都是GUID(真实的GUID1等等是出于可读性原因而使用),可以假设它们是唯一的并用作密钥。

我有一个可以合并文件的XSLT,但我无法弄清楚如何覆盖属性等。

这是我目前的XSLT,它基本上只是一个合并。但它只是将两个文件混合在一起。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:param name ="filename"></xsl:param>

  <xsl:template match="/BookClub">
    <xsl:copy>
      <xsl:apply-templates select="*"/>
      <xsl:apply-templates select="document($filename)/BookClub/*"/>
    </xsl:copy>
  </xsl:template>

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

1 个答案:

答案 0 :(得分:0)

我仍然对你的问题中的许多事情感到困惑,但为了推动这一进程,让我们考虑两个文件:

BookClub.xml(这是用于XSL转换的输入XML文件的文件):

<BookClub ref="WashingtonClub101">
    <ReadingList ref="SummerReadingList">
        <Book>
            <Id>GUID1</Id>
            <Name>Favorite Book</Name>
            <Author>Favorite Author</Author>
            <Cost>$12.00</Cost>
        </Book>
        <Book>
            <Id>GUID2</Id>
            <Name>Boring Book</Name>
            <Author>Fun Author</Author>
            <Cost>$30.00</Cost>
        </Book>
        <Book>
            <Id>GUID4</Id>
            <Name>Summer Book 7</Name>
        </Book>
        <Remove Id="GUID5" />
    </ReadingList>
</BookClub>

file2.xml(这是一个外部文件,其路径将作为参数传递给样式表):

<ReadingList Id="SummerReadingList">
    <Book>
        <Id>GUID3</Id>
        <Name>Summer Book 1</Name>
        <Author>Favorite Author</Author>
        <Cost>$40.00</Cost>
    </Book>
    <Book>
        <Id>GUID4</Id>
        <Name>Summer Book 2</Name>
        <Author>Favorite Author</Author>
        <Cost>$40.00</Cost>
    </Book>
    <Book>
        <Id>GUID5</Id>
        <Name>Summer Book 3</Name>
        <Author>Favorite Author</Author>
        <Cost>$40.00</Cost>
    </Book>
</ReadingList>

现在,以下样式表:

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

<xsl:param name="filepath2" select="'file2.xml'"/>

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

<xsl:template match="ReadingList">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <xsl:apply-templates select="document($filepath2)/ReadingList/Book[not(Id=current()/Book/Id or Id=current()/Remove/@Id)]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Remove"/>

</xsl:stylesheet>

如上所述,将返回:

<?xml version="1.0" encoding="UTF-8"?>
<BookClub ref="WashingtonClub101">
   <ReadingList ref="SummerReadingList">
      <Book>
         <Id>GUID1</Id>
         <Name>Favorite Book</Name>
         <Author>Favorite Author</Author>
         <Cost>$12.00</Cost>
      </Book>
      <Book>
         <Id>GUID2</Id>
         <Name>Boring Book</Name>
         <Author>Fun Author</Author>
         <Cost>$30.00</Cost>
      </Book>
      <Book>
         <Id>GUID4</Id>
         <Name>Summer Book 7</Name>
      </Book>
      <Book>
         <Id>GUID3</Id>
         <Name>Summer Book 1</Name>
         <Author>Favorite Author</Author>
         <Cost>$40.00</Cost>
      </Book>
   </ReadingList>
</BookClub>

为了合并其他文件(或多个文件),我们需要了解您打算如何将文件路径传递给转换过程:每个路径作为单个参数,还是包含许多路径或......的字符串?

我也看到文件没有完全相同的结构。如果这是您的真实情况,那么您将无法使用相同的代码处理它们。

最后,不清楚外部文件本身之间是否存在冲突 - 如果是,则需要如何处理这些冲突。