RegEx用于捕获和替换元素textContent

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (6)

我想在两个示例中替换“name”节点的值。我使用正则表达式组来匹配它并替换。分组工作正在进行,但替换却没有。

input 1
<xml
   <user:address>.../</user:address>
   <user:name>foo</user:name>
</xml>

input 2

<xml
   <user:address>.../</user:address>
   <street:name>bar</street:name>
</xml>


private static final String NAME_GROUP = "name";
public static final Pattern pattern = Pattern.compile("<.*:name>" + "(?<" + NAME + ">.*)</.*:name>");

final Matcher nameMatcher = pattern.matcher(str);
final String s = nameMatcher.find() ? nameMatcher.group(NAME_GROUP) : null;
System.out.println(s);

//foo
//bar

现在当我更换

String output = nameMatcher.replaceFirst("hello")
 I get 
 hello</xml>

虽然我期待以下

<xml
       <user:address>.../</user:address>
       <user:name>hello</user:name>
    </xml>

对于这两个例子。为什么小组在工作但不能替换?

提问于
用户回答回答于

假设这只是一个示例,并且您没有尝试使用正则表达式解析XML,您可以使用此方法。这里我们匹配并捕获前面的字符串和后面的字符串在不同的捕获组中。在替换中,我们使用这些组的反向引用将before-string和after-string返回到最终输出中。

final String str = "<xml\n" + 
        "   <user:name>foo</user:name>\n" + 
        "   <user:address>.../</user:address>\n" + 
        "   <user:name>foo</user:name>\n" + 
        "</xml>";

final String NAME_GROUP = "name";
final Pattern pattern = Pattern.compile("(<[^:]+:name>)(?<" + NAME_GROUP + ">.*?)(</[^:]+:name>)");
final Matcher m = pattern.matcher(str);

StringBuilder sb = new StringBuilder();
while (m.find()) {
    if (m.group(NAME_GROUP) != null) {
        m.appendReplacement( sb, m.group(1) + "hello" + m.group(3) );
    }
}
m.appendTail(sb);

System.out.println(sb);

输出:

<xml
   <user:name>hello</user:name>
   <user:address>.../</user:address>
   <user:name>hello</user:name>
</xml>
用户回答回答于

我的猜测是,我们在这里用一些新名称替换name元素。一种方法是我们创建三个捕获组,一个作为开放标记的左边界,一个用于我们要替换的所需输出,第三个用于结束标记:

(<.+?:name>)(.+?)(<\/.+?:name>)

演示

正则表达式

如果不需要此表达式,可以在regex101.com中对其进行修改或更改。

RegEx电路

jex.im还有助于可视化表达式。

测试

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "(<.+?:name>)(.+?)(<\\/.+?:name>)";
final String string = "<xml\n"
     + "   <user:address>.../</user:address>\n"
     + "   <user:name>foo</user:name>\n"
     + "</xml>\n"
     + "<xml\n"
     + "   <user:address>.../</user:address>\n"
     + "   <street:name>bar</street:name>\n"
     + "</xml>\n"
     + "<xml\n"
     + "       <user:address>.../</user:address>\n"
     + "       <user:name>hello</user:name>\n"
     + "    </xml>";
final String subst = "\\1Any New Name You Wish Goes Here\\3";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

// The substituted value will be contained in the result variable
final String result = matcher.replaceAll(subst);

System.out.println("Substitution result: " + result);

编辑:

如果我们希望有<name></name>标签,我们可以更新表达式并使标签的第一部分可选:

(<(.+?:)?name>)(.+?)(<\/(.+?:)?name>)

DEMO

扫码关注云+社区

领取腾讯云代金券