【问题标题】:Convert XML to XML after sorting using XSLT使用 XSLT 排序后将 XML 转换为 XML
【发布时间】:2012-11-02 02:06:16
【问题描述】:

我正在尝试使用 XSLT 将 XML 转换为 XML。输出 XML 应根据输入 XML 中的 ModificationTime 元素进行排序。 下面是xml代码。

<?xml version="1.0" encoding="UTF-8"?>
<Process>
<currentDayAndHour>@Fri16</currentDayAndHour>

<!-- Few elements here. Need to retain them -->


<rowCount>1</rowCount>
<currentRow>1</currentRow>


<ClientList>
 <Status>0</Status>
 <ServerResponse>
  <Code>0</Code>
  <Text>OK</Text>
</ServerResponse>
<ServiceStartTime>2012-11-09 16:06:42.786</ServiceStartTime>
<ServiceEndTime>2012-11-09 16:06:42.827</ServiceEndTime>
<Files>
  <File>
    <Name>test.20121107215230411.txt</Name>
    <Size>29</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1352343152</ModificationTime>
    <Owner>19737</Owner>
    <Group>70902</Group>
  </File>
  <File>
    <Name>test.20121107183757513.txt</Name>
    <Size>29</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1352331478</ModificationTime>
    <Owner>19737</Owner>
    <Group>70902</Group>
  </File>
  <File>
    <Name>test1.20121107215230500.txt</Name>
    <Size>32</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1352343152</ModificationTime>
    <Owner>19737</Owner>
    <Group>70902</Group>
  </File>
  <File>
    <Name>test1.txt</Name>
    <Size>32</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1352323788</ModificationTime>
    <Owner>65174</Owner>
    <Group>75431</Group>
  </File>
  <File>
    <Name>HMP_test.txt</Name>
    <Size>28</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1352199478</ModificationTime>
    <Owner>19737</Owner>
    <Group>70902</Group>
  </File>
  <File>
    <Name>test1.20121107183757585.txt</Name>
    <Size>32</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1352331478</ModificationTime>
    <Owner>19737</Owner>
    <Group>70902</Group>
  </File>
  <File>
    <Name>client_access.20121108101411179.txt</Name>
    <Size>4182</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1352387653</ModificationTime>
    <Owner>19737</Owner>
    <Group>70902</Group>
  </File>
  <File>
    <Name>TechMtngAgenda.txt</Name>
    <Size>107</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1352044842</ModificationTime>
    <Owner>19737</Owner>
    <Group>70902</Group>
  </File>
  <File>
    <Name>test.txt</Name>
    <Size>29</Size>
    <Type>Regular</Type>
    <Permissions>-rw-r--r--</Permissions>
    <ModificationTime>1350063313</ModificationTime>
    <Owner>19737</Owner>
    <Group>70902</Group>
  </File>
</Files>
</ClientList>
<currentDocument>1</currentDocument>
</Process>

我需要包含所有输入元素的输出 XML,但 Files 标记应包含每个 File,按 ModificationTime 的递增顺序排列。我对 XSLT 有点陌生。我尝试使用 xsl:sort 但无法获得所需的结果。

【问题讨论】:

    标签: xml xslt sorting


    【解决方案1】:

    这个样式表将在 XSLT 1.0 中做你想做的事情

    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <!-- Identity template -->
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="Files">
        <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates select="File">
            <xsl:sort order="ascending" data-type="number" select="ModificationTime"/>
          </xsl:apply-templates>      
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    此样式表将在 XSLT 2.0 中执行您想要的操作

    <xsl:stylesheet
      version="2.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs">
    
      <!-- Identity template -->
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="Files">
        <xsl:copy>
          <xsl:sequence select="@*"/>
          <xsl:perform-sort select="File">
            <xsl:sort order="ascending" select="xs:integer(ModificationTime)"/>
          </xsl:perform-sort>      
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    在这两种情况下,Identity 模板都用于精确复制文档,并引入了单个 xsl:template 来覆盖 Files 元素的处理。在 XSLT 1.0 示例中,xsl:apply-templatesxsl:sort 一起使用,以按ModificationTimeFile 元素进行排序。 &lt;xsl:apply-templates select="File"&gt; 对已排序的 File 元素的处理将传递回 Identity 模板,因此它可能会被进一步覆盖。

    在 XSLT 2.0 示例中,xsl:sequence 用于将输入节点直接插入到结果树中。同样xsl:perform-sort 直接返回排序后的序列,而不是执行额外的指令来复制元素。请注意,这些更改可能会使样式表的执行速度更快,但也会降低未来维护的灵活性。当您直接选择事物时,添加覆盖要困难得多。 XSLT 1.0 样式表或其处理方式可以在 XSLT 2.0 中完成,而无需进行重大更改。最后一点,这两个例子都省略了Files 的任何node() 子元素,它们不是File 元素。要捕获那些您可以在 XSLT 1.0 中添加的内容

    <xsl:apply-templates select="node()[not(self::File)]"/>
    

    或仅在 XSLT 2.0 中

    <xsl:apply-templates select="node() except File"/>
    

    <xsl:sequence select="node() except File"/>
    

    【讨论】:

    • except 运算符仅在 XPath 2.0 中可用——即在 XSLT 2.0 中。请正确。
    • 另外,最好使用:not(self::File) 而不是 not(name() = 'File')
    • 非常感谢您的帮助。
    猜你喜欢
    • 2013-04-24
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2019-04-11
    • 1970-01-01
    • 2017-12-25
    • 1970-01-01
    相关资源
    最近更新 更多