将属性添加到HTML代码

时间:2015-05-04 04:11:57

标签: java groovy

如何转换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;
}

2 个答案:

答案 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"/> - 由于另一个属性的值中存在类似属性的文本,因此会中断。

这些案例中的每一个都可以通过某种方式修改模式来修复(虽然我不确定最后一个),但是当它中断时你可以找到另一种情况。所以这种技术最好用于程序生成的输入,而不是人类编写的输入,即使这样,你也应该注意该程序的输入来自哪里(它可以很容易地包含属性值,如同最后一个例子)。