我正在尝试使用java中的正则表达式来更改xml,但我找不到正确的方法。我有一个像这样的xml(简化):
<ROOT>
<NODE ord="1" />
<NODE ord="3,2" />
</ROOT>
xml实际上显示了一个句子,其节点,块......以两种语言显示,并且具有更多属性。每个句子都加载在两个RichTextAreas中(一个用于源语句,另一个用于翻译的句子)。
我需要做的是将样式属性添加到其ord属性中具有特定值的每个节点(此样式属性将显示两种语言之间的对应关系,例如当您将鼠标悬停在单词上时,Google翻译会执行此操作)。我知道这可以使用DOM(获取所有NODE节点,然后逐个查看ord属性)来完成,但我正在寻找最快的方式来进行更改,因为它将在我的GWT的客户端执行应用程序。
当该ord属性具有单个值时(如在第一个节点中),只需将xml作为字符串并使用replaceAll()函数即可。问题是当属性具有组合值时(如在第二个节点中)。
例如,如果我要查找的值是2,我怎么能添加该属性?我相信这可以使用正则表达式完成,但我无法弄清楚如何。任何提示或帮助都会受到赞赏(即使它不使用regexp和replaceAll函数)。
提前致谢。
答案 0 :(得分:1)
String resultString = subjectString.replaceAll("<NODE ord=\"([^\"]*\\b2\\b[^\"]*)\" />", "<NODE ord=\"$1\" style=\"whatever\"/>");
会找到具有单个<NODE>
属性且价值为“2”(或“1,2”或“2,3”或“1,2,3”)的任何ord
标记但不是“12”)并添加style
属性。
这个 快速而且肮脏,在这里很多人建议不要这样做,但对于一次性的快速工作,它应该没问题。
<强>解释强>
<NODE ord=" # Match <NODE ord:" verbatim
( # Match and capture...
[^"]* # any number of characters except "
\b2\b # "2" as a whole word (surrounded by non-alphanumerics)
[^"]* # any number of characters except "
) # End of capturing group
" /> # Match " /> verbatim
答案 1 :(得分:1)
XPath可以为您完成此操作。你可以选择:
/ROOT/NODE[contains(concat(',', @ord, ','), ',2,')]
由于您打算在客户端上使用GWT,您可以尝试gwtxslt。有了它,您可以指定一个XSLT样式表来为您进行转换(即添加属性):
XsltProcessor processor = new XsltProcessor();
processor.importStyleSheet(styleSheetText);
processor.importSource(sourceText);
processor.setParameter("ord", "2");
processor.setParameter("style", "whatever");
String resultString = processor.transform();
// do something with resultString
其中styleSheetText
可以是
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="ord" select="''" />
<xsl:param name="style" select="''" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="NODE">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:if test="contains(concat(',', @ord, ','), concat(',', $ord, ','))">
<xsl:attribute name="style">
<xsl:value-of select="$style" />
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
请注意,我使用concat()
来阻止逗号分隔列表中@ord
的属性值实际为的部分匹配。
答案 2 :(得分:1)
我正在尝试使用java中的正则表达式来更改xml,但我找不到正确的方法。
那是因为没有正确的方法。正则表达式不是操纵XML的正确方法。那是因为XML不是常规语法(这是计算机科学中的技术术语,而不是普遍的侮辱。)
答案 3 :(得分:0)
这可能听起来有些过分,但我会考虑使用标准DOM解析器来读取片段,使用setAttribute()调用对其进行修改,然后再将其写出来。我知道你说效率很重要,但这需要多长时间?测试显示老化的2GHz奔腾60毫秒。
这种方法对于评论,跨行等分割的东西会更强大。它也更有可能为您提供格式良好的XML。此外,如果某些值存在,您只需要执行此操作就会变得微不足道。
public class AddStyleExample {
public static void main(final String[] args) {
String input = "<ROOT> <NODE ord=\"1\" /> <NODE ord=\"3,2\" /> </ROOT>";
try {
final DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(false);
DocumentBuilder builder;
builder = factory.newDocumentBuilder();
final Document doc = builder.parse(new InputSource(
new StringReader(input)));
NodeList tags = doc.getElementsByTagName("NODE");
for (int i = 0; i < tags.getLength(); i++) {
Element node = (Element) tags.item(i);
node.setAttribute("style", "example value");
}
StringWriter writer = new StringWriter();
final StreamResult result = new StreamResult(writer);
final Transformer t = TransformerFactory.newInstance()
.newTransformer();
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.transform(new DOMSource(doc), result);
System.out.println(writer.toString());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}