【问题标题】:Multiple XSLT files to single XSLT file for 2 different xml files多个 XSLT 文件到单个 XSLT 文件,用于 2 个不同的 xml 文件
【发布时间】:2011-07-16 20:25:29
【问题描述】:

这是我的 xml 文件:

<?xml version="1.0" encoding="windows-1250"?>
<CONTACTS>
    <CONTACT>
        <FirstName>Ford</FirstName>
        <LastName>Pasteur</LastName>
        <EMail>pasteur.ford@yahoo.com</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>Jack</FirstName>
        <LastName>Sully</LastName>
        <URL>http://www.facebook.com/profile.php?id=1000474277</URL>
    </CONTACT>
    <CONTACT>
        <FirstName>Colombo</FirstName>
        <LastName>Chao</LastName>
        <EMail>chao.colombo@liberto.it</EMail>
    </CONTACT>
</CONTACTS>

我使用下面的 XSLT 文件作为我的第一个版本的 xml 输出。

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

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

    <xsl:template match="CONTACT">
        <xsl:copy>
               <Customer-ID>
               <xsl:value-of select="generate-id(.)"/> 
               </Customer-ID>
              <xsl:copy-of select="FirstName|LastName|URL"/>
              <Facebook-ID>
            <xsl:choose>
                <xsl:when test="URL">
                    <xsl:value-of select="substring-after(URL,'?id=')"/>
                </xsl:when>
                <xsl:otherwise>

                </xsl:otherwise>
            </xsl:choose>
        </Facebook-ID>
            <EMAILS>
                <xsl:apply-templates select="EMail"/>
            </EMAILS>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="EMail">
        <EMail> 
            <Type><xsl:value-of select="substring-before(
                    substring-after(.,'@'),
                    '.')"/>
            </Type>
            <Value><xsl:value-of select="."/></Value>
        </EMail>
    </xsl:template>

</xsl:stylesheet>

我从上述 XSLT 文件输出的第一个版本的 xml:

<?xml version="1.0" encoding="windows-1250"?>
<CONTACTS>
    <CONTACT>
    <Customer-ID>N65539</Customer-ID>
    <FirstName>Ford</FirstName>
    <LastName>Pasteur</LastName>
    <EMAILS>
    <EMail>
    <Type>yahoo</Type>
    <Value>pasteur.ford@yahoo.com</Value>
    </EMail>
    </EMAILS>
    </CONTACT>
    <CONTACT>
    <Customer-ID>N65546</Customer-ID>
     <FirstName>Jack</FirstName>
     <LastName>Sully</LastName>
     <URL>http://www.facebook.com/profile.php?id=1000474277</URL>
    <Facebook-ID>1000474277</Facebook-ID>
    <EMAILS/>
    </CONTACT>
    <CONTACT>
    <Customer-ID>N65553</Customer-ID>
    <FirstName>Colombo</FirstName>
    <LastName>Chao</LastName>
    <EMAILS>
    <EMail>
    <Type>liberto</Type>
    <Value>chao.colombo@liberto.it</Value>
    </EMail>
    </EMAILS>
    </CONTACT>
</CONTACTS>

这是我的第二个 XSLT 文件:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="CONTACT">
<xsl:copy>
    <Customer-ID>
        <xsl:value-of select="Customer-ID"/>
    </Customer-ID>

    <FirstName>
        <xsl:value-of select="FirstName"/>
    </FirstName>

    <LastName>
        <xsl:value-of select="LastName"/>
    </LastName>

    <gmail>
            <xsl:value-of select="EMAILS/EMail[Type='gmail']/Value"/>
    </gmail>

    <yahoo>
            <xsl:value-of select="EMAILS/EMail[Type='yahoo']/Value"/>
    </yahoo>

    <liberto>
            <xsl:value-of select="EMAILS/EMail[Type='liberto']/Value"/>
    </liberto>

    <URL>
            <xsl:value-of select="URL"/>
    </URL>

    <Facebook-ID>
             <xsl:value-of select="Facebook-ID"/>
    </Facebook-ID>

      </xsl:copy>
</xsl:template>

这是我从第二个 XSLT 文件中的最终 xml 输出:

<?xml version="1.0" encoding="windows-1250"?>
<CONTACTS>

    <CONTACT>
    <Customer-ID>N65539</Customer-ID>
    <FirstName>Ford</FirstName>
    <LastName>Pasteur</LastName>
    <gmail/>
    <yahoo>pasteur.ford@yahoo.com</yahoo>
    <liberto/>
    <URL/>
    <Facebook-ID/>
    </CONTACT>

    <CONTACT>
    <Customer-ID>N65546</Customer-ID>
    <FirstName>Jack</FirstName>
    <LastName>Sully</LastName>
    <gmail/>
    <yahoo/>
    <liberto/>
    <URL>http://www.facebook.com/profile.php?id=1000474277</URL>
    <Facebook-ID>1000474277</Facebook-ID>
    </CONTACT>

    <CONTACT>
    <Customer-ID>N65553</Customer-ID>
    <FirstName>Colombo</FirstName>
    <LastName>Chao</LastName>
    <gmail/>
    <yahoo/>
    <liberto>chao.colombo@liberto.it</liberto>
    <URL/>
    <Facebook-ID/>
    </CONTACT>
</CONTACTS>

如何将这两个 XSLT 文件合并为一个 XSLT 文件以获得最终的 XML 输出。

我该如何进行呢?因为有两个相似类型的不同xml文件。

我正在使用 Eclipse Hellios run as -->XSL 转换来查看输出。

【问题讨论】:

  • 努力+1。我已将您在 XSLT 2.0 rec. 中找到的两阶段示例改编为您的用例 XSLT 1.0。

标签: xml eclipse xslt


【解决方案1】:

在 XSLT 应用程序中经常使用执行一系列转换,尽管完全在 XSLT 1.0 中执行此操作需要使用特定于供应商的 xxx:node-set() 函数。在 XSLT 2.0 中不需要这样的扩展,因为那里消除了臭名昭著的 RTF 数据类型。

这里是一个例子(太简单了没有意义,但完整地说明了这是如何完成的):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
   <xsl:variable name="vrtfPass1">
    <xsl:apply-templates select="/*/*"/>
   </xsl:variable>

   <xsl:variable name="vPass1"
        select="ext:node-set($vrtfPass1)"/>

   <xsl:apply-templates mode="pass2"
        select="$vPass1/*"/>
 </xsl:template>

 <xsl:template match="num[. mod 2 = 1]">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="num" mode="pass2">
  <xsl:copy>
    <xsl:value-of select=". *2"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

产生想要的正确结果

<num>2</num>
<num>6</num>
<num>10</num>
<num>14</num>
<num>18</num>

说明

  1. 第一步,转换 XML 文档,结果定义为变量 $vrtfPass1 的值。这只会复制具有奇数(不是偶数)的num 元素。

  2. $vrtfPass1 变量属于 RTF 类型,不能直接用于 XPath 表达式,因此我们使用 EXSLT(由大多数 XSLT 1.0 处理器实现)将其转换为普通树) 函数ext:node-set 并定义另一个变量——$vPass1,其值为这棵树。

  3. 我们现在在我们的转换链中执行第二个转换 -- 在第一个转换的结果上,将其保留为变量 $vPass1 的值。为了不与第一次通过模板混淆,我们指定新处理应该处于命名模式,称为“pass2”。在此模式下,任何num 元素的值都会乘以 2。

XSLT 2.0 解决方案(无 RTF):

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:variable name="vPass1" >
   <xsl:apply-templates select="/*/*"/>
  </xsl:variable>
   <xsl:apply-templates mode="pass2"
        select="$vPass1/*"/>
 </xsl:template>

 <xsl:template match="num[. mod 2 = 1]">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="num" mode="pass2">
  <xsl:copy>
    <xsl:value-of select=". *2"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

【讨论】:

  • @karthik rangaraj:如果我很好地理解了您的问题,那么您是在问如何将第二次转换应用于第一次转换的结果。在我的回答中,我在一个说明该技术的示例中展示了这一点。您可以使用相同的技术将两个转换链接在一起,或者通常将任何两个或多个转换链接在一起。仔细阅读解释。
  • 技术很棒。我已经理解你的技术和解释。 @empo:使用了您的技术,一切正常。谢谢你的技术。
【解决方案2】:

您可以使用xsl:import 重用您的XSLT 文件,然后使用@Dimitre 的回答中解释的技术如下:

<xsl:stylesheet version="1.0" 
    xmlns:exslt="http://exslt.org/common"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="exslt">

    <xsl:import href="phase1.xsl"/>
    <xsl:import href="phase2.xsl"/>

    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:variable name="intermediate">
            <xsl:apply-templates select="/CONTACTS/CONTACT" mode="phase1"/>
        </xsl:variable>
           <CONTACTS>
        <xsl:apply-templates select="exslt:node-set($intermediate)" 
         mode="phase2"/>
           </CONTACTS>
    </xsl:template>

</xsl:stylesheet>

地点:

  • phase1.xsl 和 phase2.xsl 是您的两个 xslt 转换
  • transforms 稍作修改,为每个模板添加了mode。例如,phase1.xsl 变换:

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" mode="phase1"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="CONTACT" mode="phase1">
        <xsl:copy>
            <Customer-ID>
                <xsl:value-of select="generate-id(.)"/> 
            </Customer-ID>
            <xsl:copy-of select="FirstName|LastName|URL"/>
            <Facebook-ID>
                <xsl:choose>
                    <xsl:when test="URL">
                        <xsl:value-of select="substring-after(URL,'?id=')"/>
                    </xsl:when>
                    <xsl:otherwise>
    
                    </xsl:otherwise>
                </xsl:choose>
            </Facebook-ID>
            <EMAILS>
                <xsl:apply-templates select="EMail" mode="phase1"/>
            </EMAILS>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="EMail" mode="phase1">
        <EMail> 
            <Type><xsl:value-of select="substring-before(
                    substring-after(.,'@'),
                    '.')"/>
            </Type>
            <Value><xsl:value-of select="."/></Value>
        </EMail>
    </xsl:template>
    

对于 phase2.xsl,您显然会使用 `mode="phase2"。

当满足上述条件时,merging 转换应用于您的第一个输入 XML,将获得以下输出:

<CONTACTS>
   <CONTACT>
      <Customer-ID>d0e2</Customer-ID>
      <FirstName>Ford</FirstName>
      <LastName>Pasteur</LastName>
      <gmail/>
      <yahoo>pasteur.ford@yahoo.com</yahoo>
      <liberto/>
      <URL/>
      <Facebook-ID/>
   </CONTACT>
   <CONTACT>
      <Customer-ID>d0e9</Customer-ID>
      <FirstName>Jack</FirstName>
      <LastName>Sully</LastName>
      <gmail/>
      <yahoo/>
      <liberto/>
      <URL>http://www.facebook.com/profile.php?id=1000474277</URL>
      <Facebook-ID>1000474277</Facebook-ID>
   </CONTACT>
   <CONTACT>
      <Customer-ID>d0e16</Customer-ID>
      <FirstName>Colombo</FirstName>
      <LastName>Chao</LastName>
      <gmail/>
      <yahoo/>
      <liberto>chao.colombo@liberto.it</liberto>
      <URL/>
      <Facebook-ID/>
   </CONTACT>
</CONTACTS>

【讨论】:

  • “像魅力一样工作”谢谢。
猜你喜欢
  • 2013-08-13
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多