代码之家  ›  专栏  ›  技术社区  ›  F.P

用于将字符串重新格式化为安全XML标记的regex

  •  0
  • F.P  · 技术社区  · 15 年前

    我目前正在尝试编写一个regexreplace,以确保输入可以用作有效的XML标记,这意味着:没有空格、没有特殊字符、只有小写等…

    有没有一个共同的方法,或者我必须从头开始?

    例子:

    string Invalid = "asd(%4 asKUd n!%mn &§a_As1";  // Invalid as a tag
    
    string Valid = FormatToSafeXmlTag(Invalid);  // How to write this function?
    
    // Valid = "asd4_askud_nmna_as1"
    
    3 回复  |  直到 15 年前
        1
  •  6
  •   Welbog    15 年前

    根据 XML specification ,元素的名称按以下方式形成:

    Name   ::=  NameStartChar (NameChar)*
    

    在哪里?

    NameStartChar  ::=  ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] 
      | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] 
      | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] 
      | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
    NameChar       ::=  NameStartChar | "-" | "." | [0-9] | #xB7 
      | [#x0300-#x036F] | [#x203F-#x2040]
    

    转换为正则表达式是很简单的。

    如果要删除此定义之外的任何字符,只需反转表达式要查找的字符。

        2
  •  2
  •   Tim Pietzcker    15 年前

    XML标记(我假设您询问的是标记名)必须遵循以下规则:

    • 以字母、点、冒号或下划线开头
    • 仅包含字母、数字、点、下划线或冒号(用于命名空间)
    • 不能以开头 xml

    因此,有效标记名的regex可以是:

    ^(?!xml)[\w.:][\w\d.:]*$
    

    取决于您的regex风格(例如,.net中包含Unicode字母 \w ,标记名也是合法的)。你也可以用

    ^(?!xml)[p\{L}._:][\p{L}\p{N}._:]*$
    

    如果 \w 不包含Unicode字母。

    但是,当然您可以使用更严格的规则,而且可能不是所有的XML解析器都可以处理完整的Unicode标记名。所以最后,

    ^(?!xml)[A-Za-z._:][A-Za-z0-9._:]*$
    

    可能是你最好的选择…

        3
  •  2
  •   Amarghosh    15 年前
    • 只有小写: ^[a-z]+$
    • 第一个字符小写,(可选)剩余字符小写/数字 ^[a-z][a-z0-9]*$
    • 只有大写字母: ^[A-Z]+$
    • 第一个字符字母表,(可选)其余字符字母数字 ^[a-zA-Z][a-zA-Z0-9]*$

    编辑:要删除javascript中除小写字符以外的所有内容:

    str = str.replace(/[^a-z]/g, "");
    

    关键是当用户只输入不可接受的字符时——您将最终尝试创建一个带有空字符串的XML标记。我宁愿让用户再试一次-输入小写字符串有多困难?

    警告: 另一个边缘情况是当用户进入 xml 或任何不区分大小写的变体(感谢@tim的回答)。如果您使用的是Javascript,则不能使用Tim建议的解决方案,因为它使用的是LookBehind,这是Javascript Regex不支持的功能。

    javascript代码:

    str = str.replace(/\s/g, "_"); //replaces spaces
    
    str = str.replace(/[^a-zA-Z0-9_\-]/g, "");//trim symbols
    
    var reg = new RegExp(/^xml/i); 
    
    if(str.length == 0 || reg.test(str)) //is it empty or "xml" or "XmL" or ..
        alert("invalid regex");