Рубрики
Без рубрики

Изменение атрибута XML на Java

Узнайте, как изменять атрибуты в документе XML с помощью Java с помощью JAXP, dom4j и jOOX

Автор оригинала: baeldung.

Изменение атрибута XML на Java

1. Введение

Одним из распространенных действий при работе с XML является работа с его атрибутами. В этом учебнике мы изумим, как изменить атрибут XML с помощью Java.

2. Зависимости

Для того, чтобы запустить наши тесты, мы должны добавить JUnit и xmlunit-assertj зависимостей от нашей Мавен проект:


    org.junit.jupiter
    junit-jupiter
    5.5.0
    test

    org.xmlunit
    xmlunit-assertj
    2.6.3
    test

3. Использование JAXP

Начнем с документа XML:

Для того, чтобы обработать его, мы использовать Java API для обработки XML (JAXP) , который был в комплекте с Java с версии 1.4.

Давайте изменим обслуживание атрибут и изменить его значение на ложные .

Во-первых, мы должны построить Документ объект из файла XML, и для этого мы будем использовать ДокументОстроительФактория :

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
Document input = factory
  .newDocumentBuilder()
  .parse(resourcePath);

Обратите внимание, что для того, отключить внешняя обработка сущности (XXE) для ДокументОстроительФактория класс, мы настраиваем XMLConstants.FEATURE_SECURE_PROCESSING и http://apache.org/xml/features/disallow-doctype-decl особенности . Это хорошая практика, чтобы настроить его, когда мы разобрать ненадежные файлы XML.

После инициализации нашего входные объект, нам нужно найти узел с атрибутом, который мы хотели бы изменить. Давайте использовать XPath выражение выбрать его:

XPath xpath = XPathFactory
  .newInstance()
  .newXPath();
String expr = String.format("//*[contains(@%s, '%s')]", attribute, oldValue);
NodeList nodes = (NodeList) xpath.evaluate(expr, input, XPathConstants.NODESET);

В этом случае XPath оценить метод возвращает нам список узлов с совещенными узлами.

Давайте итерировать по списку, чтобы изменить значение:

for (int i = 0; i < nodes.getLength(); i++) {
    Element value = (Element) nodes.item(i);
    value.setAttribute(attribute, newValue);
}

Или, вместо для цикл, мы можем использовать IntStream :

IntStream
    .range(0, nodes.getLength())
    .mapToObj(i -> (Element) nodes.item(i))
    .forEach(value -> value.setAttribute(attribute, newValue));

Теперь, давайте использовать Трансформатор объект для применения изменений:

TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer xformer = factory.newTransformer();
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
Writer output = new StringWriter();
xformer.transform(new DOMSource(input), new StreamResult(output));

Если мы напечатаем выходной объект содержание, мы получим в результате XML с обслуживание атрибут изменен:

Кроме того, мы можем использовать утверждать, что метод XMLUnit если нам нужно проверить это в единице теста:

assertThat(output.toString()).hasXPath("//*[contains(@customer, 'false')]");

4. Использование dom4j

dom4j представляет собой платформу с открытым исходным кодом для обработки XML, которая интегрирована с XPath и полностью поддерживает DOM, SAX, JAXP и Java Коллекции.

4.1. Зависимость от Maven

Нам нужно добавить dom4j и джаксен зависимостей от нашей пом.xml использовать dom4j в нашем проекте:


    org.dom4j
    dom4j
    2.1.1


    jaxen
    jaxen
    1.2.0

Мы можем узнать больше о dom4j в нашей статье поддержки библиотек XML .

4.2. Использование org.dom4j.Element.addAttribute

dom4j предлагает Элемент интерфейс как абстракция для элемента XML. Мы будем использовать addAttribute метод обновления наших обслуживание атрибут.

Давайте посмотрим, как это работает.

Во-первых, мы должны построить Документ объект из файла XML – на этот раз мы будем использовать SAXЧитатель :

SAXReader xmlReader = new SAXReader();
Document input = xmlReader.read(resourcePath);
xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

Мы устанавливаем дополнительные функции для предотвращения XXE.

Как и JAXP, мы можем использовать выражение XPath для выбора узлов:

String expr = String.format("//*[contains(@%s, '%s')]", attribute, oldValue);
XPath xpath = DocumentHelper.createXPath(expr);
List nodes = xpath.selectNodes(input);

Теперь мы можем итерировать и обновлять атрибут:

for (int i = 0; i < nodes.size(); i++) {
    Element element = (Element) nodes.get(i);
    element.addAttribute(attribute, newValue);
}

Обратите внимание, что с помощью этого метода, если атрибут уже существует для данного имени, он будет заменен. В противном случае, он будет добавлен.

Для печати результатов мы можем повторно использовать код из предыдущего раздела JAXP.

5. Использование jOOX

jOOX (jOOX Object-Oriented XML) — обертка для org.w3c.dom пакет, который позволяет свободно XML создание документов и манипуляции, где DOM требуется, но слишком многословно. jOOX только обертывает базовый документ и может быть использован для повышения DOM, а не в качестве альтернативы.

5.1. Зависимость от Maven

Мы должны добавить зависимость к нашей пом.xml использовать jOOX в нашем проекте.

Для использования с Java 9 “, мы можем использовать:


    org.jooq
    joox
    1.6.2

Или с Java 6 “, у нас есть:


    org.jooq
    joox-java-6
    1.6.2

Мы можем найти последние версии джоокс и joox-java-6 в Центральном хранилище Maven.

5.2. Использование org.w3c.dom.Element.setAttribute

JOOX API сам вдохновлен j-Кери , как мы можем видеть в примерах ниже. Давайте посмотрим, как его использовать.

Во-первых, мы должны загрузить Документ :

DocumentBuilder builder = JOOX.builder();
Document input = builder.parse(resourcePath);

Теперь нам нужно выбрать его:

Match $ = $(input);

Для того, чтобы выбрать элемент клиента, мы можем использовать найти метод или выражение XPath. В обоих случаях мы получим список элементов, которые соответствуют ему.

Посмотрим на найти метод в действии:

$.find("to")
    .get()
    .stream()
    .forEach(e -> e.setAttribute(attribute, newValue));

Чтобы получить результат в Струнные , мы просто должны позвонить toString () метод:

$.toString();

6. Контрольный показатель

Для сравнения производительности этих библиотек мы использовали бенчмарк JMH.

Давайте посмотрим результаты:

| Benchmark                          Mode  Cnt  Score   Error  Units |
|--------------------------------------------------------------------|
| AttributeBenchMark.dom4jBenchmark  avgt    5  0.150 ± 0.003  ms/op |
| AttributeBenchMark.jaxpBenchmark   avgt    5  0.166 ± 0.003  ms/op |
| AttributeBenchMark.jooxBenchmark   avgt    5  0.230 ± 0.033  ms/op |

Как мы видим, для этого случая использования и нашей реализации, dom4j и JAXP имеют лучшие оценки, чем jOOX.

7. Заключение

В этом быстром учебнике мы представили, как модифицировать атрибуты XML с помощью JAXP, dom4j и jOOX. Кроме того, мы измерили производительность этих библиотек с помощью бенчмарка JMH.

Как обычно, все образцы кода, показанные здесь, доступны на GitHub .