基于Perl的HTML id属性生成器

时间:2014-10-16 17:29:25

标签: html perl

我有一个网页,其中包含来自后端数据库的信息表。在这个表中是一个(通常)唯一的密钥,由我无法控制的第三方提供。

因为HTML id属性不区分大小写,必须是唯一的,并且只能包含某些字符,所以我已经使用MD5哈希根据唯一的数据库键创建它们。密钥本身远远不符合HTML id标记标准。

#!/usr/bin/perl

use strict;
use warnings;

use Digest::MD5 qw(md5_hex);

my @extens = qw( g h i j k l m n o p q );

sub GenHTMLid {

    my $id = md5_hex( $_[0] );

    # HTML 4.01 does not allow ID's that begin with numbers
    $id =~ s/(^[0-9])/$extens[$1]/;

    return $id;
}

这似乎适用于大多数情况,但由于创建了密钥的长度(32个字符),因此不适合我的情况。

我的猜测是,使用整套小写字母字符的生成器可能需要更少的字符才能通常是唯一的。

我一直在通过CPAN和互联网搜索创建这些标签的模块,但还没找到。有没有人碰巧知道一个,或者有一个需要更少字符的解决方案?

其他信息:数据库引擎是Sybase。键(由第三方提供)是6到7个字段,用斜杠(/)字符分隔。虽然许多字段可能只包含特定值,但其中两个字段是“自由手”,并且通常包含您不希望出现在HTML ID标记中的字符,例如:()[]< > ! 〜$%,#和'空间'。整个键(所有字段和分隔符)存储在一个简单的varchar中,经过一些非常小的翻译后 - 以防止Sybase抱怨。 ' id'标签是第三方网络应用所必需的,因此我无法轻易将其更改为“数据”。

3 个答案:

答案 0 :(得分:2)

如果您不介意@choroba's solution的内存占用增加,我建议您继续使用。

否则,您可以从git使用提交哈希中获取提示:大多数情况下,前七个十六进制数字就足够了。

例如,

#!/usr/bin/env perl

use strict;
use warnings;
use Digest::SHA1 qw(sha1_hex);

run();

sub run {
    my %id;
    for my $byte (0 .. 255) {
        $id{ GenHTMLid(chr $byte) } = 1;
    }
    print scalar keys %id, "\n";
}

sub GenHTMLid { 'id' . substr( sha1_hex( $_[0] ), 0, 8) }

将打印256。我不知道你的数据库密钥空间是什么样的。如果我们有一些想法,我们可以测试该关键空间中的碰撞。

如果我们可以排除冲突,GenHTMLid的版本会在数据库键和HTML ID之间产生双射,而不会占用查找表的内存空间。

答案 1 :(得分:0)

您只需生成从azzzz等的字符串,并将映射保留为哈希:

{   # closure
    my %id;
    my $generate = 'a';
    sub GetId {
        my $dbkey = shift;
        return $id{$dbkey} ||= $generate++;
    }
}

只需运行GetId($key)即可获得相同$ key的相同ID。

答案 2 :(得分:0)

HTML id属性应该唯一地标识HTML文档中的元素。将它用于表中可能不唯一的行是没有意义的。实际上,首先将id s分配给表行并不合理,因为表通常用于统一显示数据;异常有特殊的HTML元素,包括表格页眉,页脚和列组。

我建议改用HTML5 data-* attributes。 (您仍然可以在HTML4中使用它们,它们只被视为常规属性。)data-*属性可用于将数据与特定HTML元素相关联,即使数据没有给出任何特定的语义含义。标记。 data-*属性的值不必是唯一的,并且不限于字母,数字,连字符,下划线,冒号和id等句点。

在支持它们的浏览器中,使用data-*属性使用vanilla JavaScript访问dataset属性非常简单:

HTML

<div id="foo" data-uuid="12345"></div>

的JavaScript

var foo  = document.querySelector("#foo");
var uuid = foo.dataset.uuid; // "12345" 

还有polyfill允许您在不支持它的浏览器上模拟dataset属性。

使用jQuery,您可以使用.data()方法:

$( "#foo" ).data( "uuid" ); // "12345"

下面是一个更完整(可运行)的示例。它会根据data-*属性的值更改表中特定行的背景颜色。请注意,不是简单地更改背景颜色,而是可以在AJAX请求中使用此属性的值并将其发送回服务器。

$(function() {
  var highest;

  $("tr").each(function() {
    var userid = $(this).data("userid");

    if (userid != null) {
      if (highest == null) {
        highest = $(this);
      } else if (userid > highest.data("userid")) {
        highest = $(this);
      }
    }
  });

  // Highlight the row with the highest user ID
  highest.css("background-color", "red");
});
td {
  outline: solid black 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<table>
  <caption>Stack Overflow users who need more sleep</caption>
  <tr>
    <th>Username</th>
    <th>Reputation</th>
  </tr>
  <tr data-userid="1733163">
    <td>Miller</td>
    <td>26,621</td>
  </tr>
  <tr data-userid="223226">
    <td>mpapec</td>
    <td>31,846</td>
  </tr>
  <tr data-userid="589924">
    <td>ikegami</td>
    <td>139,368</td>
  </tr>
</table>