【问题标题】:XSLT to generate another XSLT scriptXSLT 生成另一个 XSLT 脚本
【发布时间】:2012-11-20 12:30:21
【问题描述】:

在这个帖子中,我指的是我的最后一个帖子:Convert XML to CSV using XSLT - dynamic columns

引用线程中的 XSLT 脚本工作正常,但对于大型 XML 文档,性能不佳。现在我想编写一个输出另一个 XSLT 脚本的 XSLT 脚本,该脚本将输出最终的 CSV 文件。

问题:

如何编写第一个 XSLT 脚本?输出应如下所示:

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

<xsl:template match="/*">
    <xsl:text>Name;</xsl:text>
    <xsl:text>Brother;</xsl:text>
    <xsl:text>Sister</xsl:text>
    <-- this part is dynamic -->
    <xsl:apply-templates select="Person" />
</xsl:template>

<xsl:template match="Person">
    <xsl:value-of select="Name" />
    <xsl:value-of select="Brother" />
    <xsl:value-of select="Sister" />
    <-- this part is dynamic too -->
    <xsl:text>&#10;</xsl:text>
</xsl:template>
</xsl:stylesheet>

输入的 XML 文件与引用线程中的相同:

<Person>
    <Name>John</Name>
    <FamilyMembers>
        <FamilyMember>
            <Name>Lisa</Name>
            <Type>Sister</Type>
        </FamilyMember>
        <FamilyMember>
            <Name>Tom</Name>
            <Type>Brother</Type>
        </FamilyMember>
    </FamilyMembers>
</Person>
<Person>
    <Name>Daniel</Name>
    <FamilyMembers>
        <FamilyMember>
            <Name>Peter</Name>
            <Type>Father</Type>
        </FamilyMember>
    </FamilyMembers>
</Person>

对于每个不同的类型元素,在生成的 XSLT 脚本中应该有如下一行:

<xsl:text>Type;</xsl:text>

【问题讨论】:

  • 其实你不需要两外相解决方案。您需要做的就是提高 Tim 解决方案的大规模效率。您应该问的真正问题是如何进行大规模优化。

标签: xml xslt


【解决方案1】:

要编写一个输出另一个 XSLT 的 XSLT,您需要使用 &lt;xsl:element&gt; 生成输出元素,例如

<xsl:element name="xsl:text">

如果您想使用文字结果元素,请使用&lt;xsl:namespace-alias&gt;XSLT spec 有一个例子:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">

<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

<xsl:template match="/">
  <axsl:stylesheet>
    <xsl:apply-templates/>
  </axsl:stylesheet>
</xsl:template>

样式表中的任何&lt;axsl:...&gt; 元素都将在输出中变为&lt;xsl:...&gt;

【讨论】:

  • 您的解决方案最适合我的问题。使用 axsl 是我的实际方式。稍后我会测试肖恩的解决方案。
【解决方案2】:

我认为 Tim 的解决方案版本可以更好地为您服务,而不是两个外部阶段的解决方案(意思是一个样式表,该样式表编写一个可以执行的样式表)。请以您的“大型 XML 文档”作为输入来衡量此解决方案的性能。

这个 XSLT 1.0 样式表...

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

<xsl:key name="kTypes" match="Type" use="." />  
<xsl:variable name="distinct-types"
  select="/*/Person/FamilyMembers/FamilyMember/Type[
  generate-id()=generate-id(key('kTypes',.)[1])]" />

<xsl:template match="/">
  <xsl:value-of select="'Name;'" />
  <xsl:for-each select="$distinct-types">
    <xsl:value-of select="." />
    <xsl:if test="position() &lt; last()">
      <xsl:value-of select="';'" />
    </xsl:if>  
  </xsl:for-each>
  <xsl:value-of select="'&#x0A;'" />
  <xsl:apply-templates select="*/Person" />
</xsl:template>

<xsl:template match="Person">
  <xsl:value-of select="concat(Name,';')" />
  <xsl:variable name="family" select="FamilyMembers/FamilyMember" />
  <xsl:for-each select="$distinct-types">
    <xsl:variable name="type" select="string(.)" />
    <xsl:value-of select="$family/self::*[Type=$type]/Name" />
    <xsl:if test="position() &lt; last()">
      <xsl:value-of select="';'" />
    </xsl:if>  
  </xsl:for-each>
  <xsl:value-of select="'&#x0A;'" />
</xsl:template>

</xsl:stylesheet>

...将转换此输入(或大规模有效地转换其他输入)...

<t>
<Person>
    <Name>John</Name>
    <FamilyMembers>
        <FamilyMember>
            <Name>Lisa</Name>
            <Type>Sister</Type>
        </FamilyMember>
        <FamilyMember>
            <Name>Tom</Name>
            <Type>Brother</Type>
        </FamilyMember>
    </FamilyMembers>
</Person>
<Person>
    <Name>Daniel</Name>
    <FamilyMembers>
        <FamilyMember>
            <Name>Peter</Name>
            <Type>Father</Type>
        </FamilyMember>
    </FamilyMembers>
</Person>
</t>

...并生成文本...

Name;Sister;Brother;Father
John;Lisa;Tom;
Daniel;;;Peter

【讨论】:

  • 我会对其进行测试并提供反馈。可能需要一些时间。
【解决方案3】:

在此处查看为另一个 XSLT 转换生成样式表的 XSLT 转换的实际示例:

http://dnovatchev.wordpress.com/2006/10/21/a-stylesheet-to-write-xslt-code/

【讨论】:

    猜你喜欢
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    • 2011-07-26
    • 1970-01-01
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多