匹配JS中XML字符串的属性值

时间:2013-08-01 03:24:56

标签: javascript xml regex xml-parsing

我已经研究过stackoverflow并找到了类似的结果,但它并不是我想要的。

在javascript上下文中给出一个xml字符串:"<a b=\"c\"></a>"我想创建一个捕获属性值的正则表达式,包括引号

注意:如果您使用单引号,则类似。

目前我有一个针对XML规范定制的正则表达式:

[_A-Za-z][\w\.\-]*(?:=\"[^\"]*\")?

[_A-Za-z][\w\.\-]*     //This will match the attribute name.
(?:=\"[^\"]*\")?       //This will match the attribute value.


\"[^\"]*\"             //This part concerns me.

我现在的问题是,如果xml字符串如下所示:

<shout statement="Hi! \"Richeve\"."></shout>

我知道这是一个愚蠢的问题,但我只想捕捉这种情况可能发生的罕见情况(我知道编码器可以在这种情况下使用单引号)但有些情况我们不知道当前情况属性值在运行时动态更改的属性值。

所以为了更清楚,使用正确的正则表达式的结果应该是:

"Hi! \"Richeve\"."

我希望我的问题很明确。谢谢你的帮助!

PS:请注意,语言上下文是Javascript,我知道使用lookbehinds很有吸引力,但目前不支持lookbehinds。

PS:我知道解析XML真的很难,但我有一个优雅的解决方案:)所以我只需要解决这个小问题。所以这个问题只是主要关注的是捕获引号中标记的字符串标记,其中包含字符串标记内的引号。

2 个答案:

答案 0 :(得分:0)

具有匹配分隔符和嵌入式转义分隔符的内容的标准模式如下:

"[^"\\]*(?:\\.[^"\\]*)*"

忽略模式中明显的第一个和最后一个字符,以下是模式其余部分的工作原理:

[^"\\]*:使用所有字符,直到分隔符或反斜杠(在示例中匹配Hi!

(?:\\.[^"\\]*)*尝试使用单个转义字符\\.后跟一系列非分隔符/反斜杠字符(首先匹配\"Richeve然后再匹配\".例如)

就是这样。

您可以尝试使用(['"])和后引用使用更通用的分隔符方法,或者您可以只允许使用单引号的备用模式:

("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')

以下是对此技术的另一种描述,可能也会有所帮助(请参阅“字符串”一节):http://www.regular-expressions.info/examplesprogrammer.html

答案 1 :(得分:0)

描述

我非常确定在双引号属性值中嵌入双引号是不合法的。您可以在值中使用等效于双引号\x22的unicode。

然而回答这个问题,这个表达式会:

  • 允许在属性值中使用转义引号
  • 捕获属性statement的值
  • 允许属性以标记内的任何顺序显示
  • 将避免许多会在html文本
  • 中绊倒模式匹配的边缘情况
  • 不使用lookbehinds

<shout\b(?=\s)(?=(?:[^>=]|='(?:[^']|\\')*'|="(?:[^"]|\\")*"|=[^'"][^\s>]*)*?\sstatement=(['"])((?:\\['"]|.)*?)\1(?:\s|\/>|>))(?:[^>=]|='(?:[^']|\\')*'|="(?:[^"]|\\")*"|=[^'"][^\s>]*)*>.*?<\/shout>

enter image description here

实施例

示例文字

注意第一个属性中的困难边缘情况:)

<shout onmouseover=' statement="He said \"I am Inside the onMouseOver\" " ; if ( 6 > a ) { funRotate(statement) } ; ' statement="Hi! \"Richeve\"." title="sometitle">SomeString</shout>

<强>匹配

组0从打开到关闭获取整个标签 第1组获取围绕声明属性值的引用,这用于正确匹配结束引用 第2组获取语句属性值,该值可能包含\"之类的转义引号,但不包括周围的引号

[0][0] = <shout onmouseover=' statement="He said \"I am Inside the onMouseOver\" " ; if ( 6 > a ) { funRotate(statement) } ; ' statement="Hi! \"Richeve\"." title="sometitle">SomeString</shout>
[0][1] = "
[0][2] = Hi! \"Richeve\".