复制 xslt 应用模板中不存在的剩余元素 [英] Copying remaining elements not present in xslt apply template

查看:20
本文介绍了复制 xslt 应用模板中不存在的剩余元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 xslt 的新手,遇到了一个问题.我必须使用 xslt 根据预定义的顺序对 xml 文件中的元素重新排序.通过使用 xsl:copy-of 或 xsl:apply-template 并重新排序元素,我成功地做到了这一点.但是,如果源 xml 有一些 xslt 应用模板中不存在的新元素,那么这些新元素就不会被复制.就像在下面的例子中一样,元素State"在输出中丢失了.

I am new to xslt and facing a problem. I have to reorder the elements in an xml file based on a predefined order using xslt. I was successful in doing so by using the xsl:copy-of or xsl:apply-template and reordering the elements. However if the source xml has some new elements not present in the xslt apply template then these new elements are simply not getting copied. Like in the below example the element 'State' is lost in the output.

例如.原始xml

<Company>
  <Employee id="100" Name="John" >
    <Salary value="15000"/>
    <Qualification text="Engineering">
    <State name="Kerala" code="02">
    <Background text="Indian">
  </Employee>
</Company>

XSLT 按照 Qualification 、 Salary 和 Background 的顺序对元素重新排序

<?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 indent="yes"  omit-xml-declaration="yes" method="xml" />
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="Employee">
    <xsl:copy>
      <xsl:apply-templates select="Qualification"/>
      <xsl:apply-templates select="Salary" />
      <xsl:apply-templates select="Background"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

获得的输出

<?xml version="1.0" encoding="utf-8"?>
<Company>
  <Employee>
    <Qualification text="Engineering" />
    <Salary value="15000" />
    <Background text="Indian" />
  </Employee>
</Company>

需要输出

<?xml version="1.0" encoding="utf-8"?>
<Company>
  <Employee>
    <Qualification text="Engineering" />
    <Salary value="15000" />
    <Background text="Indian" />
    <State name="Kerala" code="02"/>
  </Employee>
</Company>

请告诉我 xslt 如何在现有标签重新排序完成后自动复制任何剩余的新标签.

Please tell me how xslt can copy any remaining new tags automatically after the reordering of the existing tags are done.

推荐答案

  <xsl:template match="Employee">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:apply-templates select="Qualification"/>
      <xsl:apply-templates select="Salary" />
      <xsl:apply-templates select="Background"/>
      <xsl:apply-templates select="node()[
         not(self::Qualification | self::Salary | self::Background)]" />
    </xsl:copy>
  </xsl:template>

这将首先复制属性,然后按固定顺序复制您感兴趣的特定元素,最后复制除这三个元素之外的所有内容..如果您想复制 Employee 标签而没有,请省略第一个 apply-templates(@* 一个)它的属性.

This will first copy the attributes, then the specific elements you're interested in in the fixed order, and finally everything else except those three elements. Leave out the first apply-templates (the @* one) if you want to copy the Employee tag without its attributes.

您在评论中说,即使在重新排序之后,您也希望将任何评论保留在相关元素的上方.我能想到的最有效的方法是使用.在样式表的顶层(在任何模板之外)定义它:

you say in your comment that you want to keep any comment above the element to which it pertains, even after re-ordering. The most efficient way I can think to do that would be using a key. Define this at the top level of the stylesheet (outside any templates):

<xsl:key name="elementPreamble" match="text()|comment()|processing-instruction()"
      use="generate-id(following-sibling::*[1])" />

给定任何元素节点,这提供了一种有效提取出现在此元素的开始标记和前一个结束标记(或此元素的开始标记及其父级的开始标记,如果这是其父元素的第一个子元素).样式表然后变成:

Given any element node, this provides a way to efficiently extract all the non-element nodes that occur between the start tag of this element and the end tag of the one before (or this element's start tag and its parent's start tag, if this is the first child element of its parent). The stylesheet then becomes:

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

  <xsl:key name="elementPreamble" match="text()|comment()|processing-instruction()"
        use="generate-id(following-sibling::*[1])" />

  <xsl:template match="/">
    <!-- Only process the root _element_, not any root-level comments etc.
         Without this template any comments ahead of the root element would be
         doubled in the output -->
    <xsl:apply-templates select="*" />
  </xsl:template>

  <xsl:template match="@*|text()|comment()|processing-instruction()">
    <xsl:copy/>
  </xsl:template>

  <xsl:template match="*">
    <!-- any preamble for this element -->
    <xsl:apply-templates select="key('elementPreamble', generate-id())" />
    <xsl:copy>
      <xsl:apply-templates select="@* | *" />
      <!-- any "post-amble" between the last child element (if any) and this
           element's own closing tag -->
      <xsl:apply-templates select="(text()|comment()|processing-instruction())[
           not(following-sibling::*)]" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Employee">
    <xsl:copy>
      <xsl:apply-templates select="Qualification"/>
      <xsl:apply-templates select="Salary" />
      <xsl:apply-templates select="Background"/>
      <!-- other elements -->
      <xsl:apply-templates select="*[
         not(self::Qualification | self::Salary | self::Background)]" />
      <!-- "post-amble" -->
      <xsl:apply-templates select="(text()|comment()|processing-instruction())[
           not(following-sibling::*)]" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

给定输入

<!-- Details of the company's employees -->
<Company>
  <Employee id="100" Name="John" >
    <!-- salary -->
    <!-- check this with HR -->
    <Salary value="15000"/>
    <Qualification text="Engineering"/>
    <!-- the employee's home state -->
    <State name="Kerala" code="02"/>
    <!-- the employee's background -->
    <Background text="Indian"/>
    <!-- this is the end of the record -->
  </Employee>
</Company>

这个样式表产生输出

<!-- Details of the company's employees -->
<Company>
  <Employee>
    <Qualification text="Engineering"/>
    <!-- salary -->
    <!-- check this with HR -->
    <Salary value="15000"/>
    <!-- the employee's background -->
    <Background text="Indian"/>
    <!-- the employee's home state -->
    <State name="Kerala" code="02"/>
    <!-- this is the end of the record -->
  </Employee>
</Company>

注释仍然附加到最近的后续元素,其顺序与它们在输入文档中出现的顺序相同.

Comments remain attached to their nearest following element, in the same order they appeared in the input document.

这篇关于复制 xslt 应用模板中不存在的剩余元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆