非字母非数字顺序的 XSLT Order 类 [英] XSLT Order classes in a non-alphabetical non-numerical order

查看:29
本文介绍了非字母非数字顺序的 XSLT Order 类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经研究过这个问题,但我发现的建议似乎相当复杂,而且适用于更一般的情况.对于这个场景,或许有更简洁的解决方案,也就是更具体.

我有大量的 html 文件,如下所示:

<头><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/><title>t</title><身体><div class="a"><div class="f">f1</div><div class="e">e1</div><div class="e">e2</div><div class="g">g</div><div class="c">c1</div><div class="b"><div class="ba">ba</div><div class="bb">bb</div>

<div class="c">c2</div><div class="f">f2</div><div class="d">d</div><div class="c">c3</div>

...</html>

规则 1我想以非字母和非数字的类属性的特定顺序对 div class="a" 内的 div 进行排序.出于本示例的目的,我们的最终顺序如下:

  • g
  • f
  • b
  • c
  • e
  • d

在我的真实例子中,列表要长得多.

规则 2如果对于给定的类属性有多个节点,那么它们应该以与原始文件中相同的顺序保留,例如:

  • c1
  • c2
  • c3

请注意,在我的真实示例中,这些值不会按字母数字顺序排列.

规则 3不能影响子节点的顺序,例如:

  • bb

请注意,在我的真实示例中,这些值也不会按字母数字顺序排列.

最终输出应如下所示:

<头><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/><title>t</title><身体><div class="a"><div class="g">g</div><div class="f">f1</div><div class="f">f2</div><div class="b"><div class="ba">ba</div><div class="bb">bb</div>

<div class="c">c1</div><div class="c">c2</div><div class="c">c3</div><div class="e">e1</div><div class="e">e2</div><div class="d">d</div>

...</html>

我一开始想:

  1. 在类属性值前添加一个数字,例如将 class="g" 重命名为 class="01g" 等
  2. 按字母数字顺序排列类
  3. 删除数字,例如将 class="01g" 重命名为 class="g" 等

但是我不喜欢这个解决方案,因为它需要太多的转换.

我真正想要的是提出更优雅的解决方案.也许我会定义一个有序的类值列表,一个聪明的索引会以某种方式将节点按定义的顺序排列?

您有什么建议可以添加到我的 xslt 模板中吗?

<xsl:output omit-xml-declaration="yes" indent="yes"/><xsl:strip-space elements="*"/><xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:模板></xsl:stylesheet>

解决方案

AFAICT,你想做如下事情:

XSLT 1.0

<xsl:output method="xml" version="1.0" omit-xml-declaration="yes" encoding="UTF-8" indent="yes"/><xsl:strip-space elements="*"/><!-- 身份变换--><xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:模板><xsl:template match="div[@class='a']"><xsl:variable name="sort-order">gfbced</xsl:variable><xsl:copy><xsl:apply-templates select="@*|node()"><xsl:sort select="string-length(substring-before($sort-order, @class))" data-type="number" order="ascending"/></xsl:apply-templates></xsl:copy></xsl:模板></xsl:stylesheet>

<小时>

要容纳不是单个字符的类值,您可以使用:

<xsl:variable name="sort-order">|g|f|b|c|e|d|</xsl:variable><xsl:copy><xsl:apply-templates select="@*|node()"><xsl:sort select="string-length(substring-before($sort-order, concat('|', @class, '|')))" data-type="number" order="ascending"/></xsl:apply-templates></xsl:copy></xsl:模板>

I have researched this problem but the suggestions that I have found seems to be rather convoluted and for a more general scenario. Perhaps there is a more concise solution for this scenario, that is more specific.

I have a large number of html files like the following:

<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
    <title>t</title>
  </head>
  <body>
    <div class="a">
      <div class="f">f1</div>
      <div class="e">e1</div>
      <div class="e">e2</div>
      <div class="g">g</div>
      <div class="c">c1</div>
      <div class="b">
        <div class="ba">ba</div>
        <div class="bb">bb</div>
      </div>
      <div class="c">c2</div>
      <div class="f">f2</div>
      <div class="d">d</div>
      <div class="c">c3</div>
    </div>
    ...
  </body>
</html>

Rule # 1 I want to order the div's inside div class="a" in a specific order of their class attribute that is non-alphabetic and non-numeric. For the purpose of this example, let's the final order be the following:

In my real examples, the list is much longer.

Rule # 2 If for a given class attribute there is more than one node, then they should be left in the same order as in the original file, for instance:

Please notice that in my real examples these values would not be in alphanumerical order.

Rule # 3 The order of child nodes must not be affected, for instance:

Please notice that in my real examples these values would not be in alphanumerical order either.

The final output should be like the following:

<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
    <title>t</title>
  </head>
  <body>
    <div class="a">
      <div class="g">g</div>
      <div class="f">f1</div>
      <div class="f">f2</div>
      <div class="b">
        <div class="ba">ba</div>
        <div class="bb">bb</div>
      </div>
      <div class="c">c1</div>
      <div class="c">c2</div>
      <div class="c">c3</div>
      <div class="e">e1</div>
      <div class="e">e2</div>
      <div class="d">d</div>
    </div>
    ...
  </body>
</html>

I have thought at first to:

  1. Prepend a number to the class attribute value, for instance rename class="g" to class="01g", etc
  2. Order the classes in alphanumerical order
  3. Remove the number, for instance rename class="01g" to class = "g", etc

However I dislike this solution because it requires too many transformations.

What I would really like is to come up with a more elegant solutions. Perhaps I would define an ordered list of class values and a clever index would somehow put the nodes in that defined order?

Do you have any suggestions to add to my xslt template?

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

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

</xsl:stylesheet>

解决方案

AFAICT, you want to do something like:

XSLT 1.0

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

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

<xsl:template match="div[@class='a']">
    <xsl:variable name="sort-order">gfbced</xsl:variable>
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:sort select="string-length(substring-before($sort-order, @class))" data-type="number" order="ascending"/>
        </xsl:apply-templates>  
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>


To accommodate class values that are not single characters, you can use:

<xsl:template match="div[@class='a']">
    <xsl:variable name="sort-order">|g|f|b|c|e|d|</xsl:variable>
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:sort select="string-length(substring-before($sort-order, concat('|', @class, '|')))" data-type="number" order="ascending"/>
        </xsl:apply-templates>  
    </xsl:copy>
</xsl:template>

这篇关于非字母非数字顺序的 XSLT Order 类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆