如何转换html输入字符串,它来自:
String tag = "<input type=\"submit\" class=\"cssSubmit\"/>";
到
"<input type=\"submit\" class=\"cssSubmit disable\" disabled=\"disabled\"/>"
是否有任何可能的Java或Groovy方法来执行此操作?
例如:
String convert(String input) {
//input: <input type=\"submit\" class=\"cssSubmit\"/>
//process the input string
//processedString: <input type=\"submit\" class=\"cssSubmit disable\" disabled=\"disabled\"/>
return processedString;
}
答案 0 :(得分:2)
你可以在groovy中这样做:
String tag = "<input type=\"submit\" class=\"cssSubmit\"/>"
tag = new XmlSlurper().parseText(tag).with { x ->
x.@class = 'cssSubmit disable'
x.@disabled = 'disabled'
new groovy.xml.StreamingMarkupBuilder().bind { delegate.out << x}.toString()
}
答案 1 :(得分:0)
这是我能想到的最通用的方式:
public static String editTagXML(String tag,
Map<String, String> newAttributes,
Collection<String> removeAttributes)
throws SAXException, IOException,
ParserConfigurationException, TransformerConfigurationException,
TransformerException {
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new InputSource(new StringReader(tag)));
Element root = doc.getDocumentElement();
NamedNodeMap attrs = root.getAttributes();
for (String removeAttr : removeAttributes) {
attrs.removeNamedItem(removeAttr);
}
for (Map.Entry<String, String> addAttr : newAttributes.entrySet()) {
final Attr attr = doc.createAttribute(addAttr.getKey());
attr.setValue(addAttr.getValue());
attrs.setNamedItem(attr);
}
StringWriter result = new StringWriter();
final Transformer transformer = TransformerFactory.newInstance()
.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(doc), new StreamResult(result));
return result.toString();
}
public static void main(String[] args) throws Exception {
long start = System.nanoTime();
String tag = "<input type=\"submit\" class=\"cssSubmit\"/>";
String edited = editTagXML(tag, new HashMap<String, String>() {{
put("class", "cssSubmit disable");
put("disabled", "disabled");
}}, new ArrayList<>());
long time = System.nanoTime() - start;
System.out.println(edited);
System.out.println("Time: " + time + " ns");
start = System.nanoTime();
tag = "<input type=\"submit\" class=\"cssSubmit\"/>";
editTagXML(tag, new HashMap<String, String>() {{
put("class", "cssSubmit disable");
put("disabled", "disabled");
}}, new ArrayList<>());
time = System.nanoTime() - start;
System.out.println("Time2: " + time + " ns");
}
它是丑陋的,巨大的,复杂的,抛出了大量已检查的异常并混合了属性顺序,这些属性顺序可能重要也可能不重要。它可能不是应该如何完成的。它也很慢。
这是输出:
<input class="cssSubmit disable" disabled="disabled" type="submit"/>
Time: 86213231 ns
Time2: 2379674 ns
第一次运行可能很慢,因为加载必要的库需要一段时间。第二次运行速度惊人,但我的PC也非常强大。如果您对输入设置了一些限制(例如,属性值仅引用"
,而属性值中没有"
等等),则可能有更好的方法,比如使用正则表达式或者甚至是简单的迭代。
例如,如果您的输入始终如此,那么这也可以起作用:
start = System.nanoTime();
edited = tag.replaceFirst("\"cssSubmit\"", "\"cssSubmit disable\" disabled=\"disabled\"");
time = System.nanoTime() - start;
System.out.println(edited);
System.out.println("Time3: " + time + " ns");
输出:
<input type="submit" class="cssSubmit disable" disabled="disabled"/>
Time3: 1422672 ns
嗯。有趣的是,它不是那么快。
好的,但是如果我们想要一个更通用的解决方案,但仍然足够简单怎么办?我们可以使用正则表达式:
private static final Pattern classAttributePattern
= Pattern.compile("\\bclass=\"([^\"]+)\"");
public static String disableTag(String tag) {
Matcher matcher = classAttributePattern.matcher(tag);
if (!matcher.find()) {
throw new IllegalArgumentException("Doesn't match: " + tag);
}
int start = matcher.start();
int end = matcher.end();
String classValue = matcher.group(1);
if (classValue.endsWith(" disable")) {
return tag; // already disabled
} else {
// assume that if the class doesn't end with " disable",
// then the disabled attribute is not present as well
return tag.substring(0, start)
+ "class=\"" + classValue
+ " disable\" disabled=\"disabled\""
+ tag.substring(end);
}
}
请注意,通常使用XML /(X)HTML的正则表达式极容易出错。以下是可能破坏上述代码的示例输入的非详尽列表:
<input type="submit" class="cssSubmit disable " disabled="disabled"/>
- 因为引号前的空格而中断; <input type="submit" class='cssSubmit disable' disabled="disabled"/>
- 这会破坏,因为我们的代码不期望使用单引号; <input type="submit" class = "cssSubmit" disabled="disabled"/>
- 由于=
; <input title='this is an input with class="cssSubmit" that could be changed to class="cssSubmit disable"' type="submit" class="cssSubmit" disabled="disabled"/>
- 由于另一个属性的值中存在类似属性的文本,因此会中断。这些案例中的每一个都可以通过某种方式修改模式来修复(虽然我不确定最后一个),但是当它中断时你可以找到另一种情况。所以这种技术最好用于程序生成的输入,而不是人类编写的输入,即使这样,你也应该注意该程序的输入来自哪里(它可以很容易地包含属性值,如同最后一个例子)。