groovy 向HTML标记添加属性

lhcgjxsq  于 9个月前  发布在  其他
关注(0)|答案(2)|浏览(73)

如何想转换一个html输入字符串,这是从:
第一个月

"<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;
}

字符串

svmlkihl

svmlkihl1#

你可以在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()
}​

字符串

v6ylcynt

v6ylcynt2#

这是我能想到的最常见的方法:

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"/>-这将中断,因为在另一个属性的值中有类似属性的文本。

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

相关问题