2 Вопрос: Каков наилучший способ изменить одно значение в файлах XML в Java?

вопрос создан в Sat, Sep 21, 2013 12:00 AM

У меня есть файл XML, и я знаю имя узла, для которого нужно изменить значение.

Имя узла - ipAddress.

Я могу использовать JDOM, получить документ, получить узел и изменить значение и записать его, или я могу написать файл XSLT.

Значение для изменения кода исходит из Java, поэтому мой вопрос: какой вариант лучше? Размер файла XML может быть разным.

Еще один вопрос, связанный с XSLT: возможно ли написать файл XSLT так, чтобы я не перечислял все узлы в XML, а просто указал как if node == ipAddress, затем принял новое значение и как я бы применил XSLT преобразование из Java?

Спасибо.

    
12
  1. Хороший вопрос, +1. См. Мой ответ для полного решения XSLT и ссылку на документацию одного из лучших XSLT-процессоров на основе Java.
    2011-01-13 00: 09: 38Z
  2. Что вы подразумеваете под "лучшим"? Самый удобный (самый простой), самый производительный, пригодный для больших файлов? XSLT и древовидные модели (DOM) могут быть удобны, но также используют много памяти и относительно медленны (например).
    2011-01-13 00: 31: 11Z
  3. Саксонский в значительной степени лучший. Он имеет меньшую, чем DOM, модель в памяти, поддерживает потоковую передачу больших файлов, обладает исключительным оптимизатором и поддерживает XSLT 1, XSLT 2, XQuery, XML Schema и поддерживает некоторые новые проекты стандартов.
    2011-01-13 00: 43: 32Z
  4. Здравствуйте, StaxMan. Спасибо Вам за Ваш вопрос. Я бы сказал, что является наиболее удобным и простым способом обработки таких случаев?
    2011-01-13 00: 45: 39Z
  5. @ Dimitre Novatchev: Спасибо за напоминание. Я принял первый ответ, так как было понятно, как реализовать. Мне также нравится ваш ответ, но я помню, что я провел некоторое время, читая о саксонике, и у меня все еще были вопросы, но это уже другая тема. Спасибо, Димитр. Я также пройду все мои еще не принятые ответы.
    2011-07-08 11: 11: 23Z
2 ответа                              2                         

Вы можете использовать стандартные API org.w3c.dom для получения DOM. Затем получите узел, используя стандартные API javax.xml.xpath. А затем используйте API-интерфейсы javax.xml.transform, чтобы записать его обратно.

Что-то вроде:

import java.io.File;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import org.w3c.dom.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        Document document = dbf.newDocumentBuilder().parse(new File("input.xml"));

        XPathFactory xpf = XPathFactory.newInstance();
        XPath xpath = xpf.newXPath();
        XPathExpression expression = xpath.compile("//A/B[C/E/text()=13]");

        Node b13Node = (Node) expression.evaluate(document, XPathConstants.NODE);
        b13Node.getParentNode().removeChild(b13Node);

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        t.transform(new DOMSource(document), new StreamResult(System.out));
    }
}
    
6
2013-09-21 16: 30: 50Z

Решение XSLT :

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="pNewIpAddress" select="'192.68.0.1'"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="ipAddress/text()">
  <xsl:value-of select="$pNewIpAddress"/>
  </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к любому документу, все узлы документа копируются «как есть», за исключением дочернего элемента text-узла любого элемента ipAddress (независимо от того, где этот элемент находится в документ). Последний заменяется значением внешнего предоставленного параметра с именем $pNewIpAddress.

Например, если преобразование применяется к этому документу XML :

<t>
    <a>
        <b>
          <ipAddress>127.0.0.1</ipAddress>
        </b>
        <c/>
    </a>
    <d/>
</t>

желаемый, правильный результат получен :

<t>
   <a>
      <b>
         <ipAddress>192.68.0.1</ipAddress>
      </b>
      <c/>
   </a>
   <d/>
</t>

Существует много XSLT-процессоров на основе Java, и подходящее место для понимания того, как их можно вызывать из Java, - это их документация. Одним из лучших таких процессоров XSLT является Saxon, и его документацию можно найти по адресу:

http://www.saxonica.com/documentation/documentation.xmlа>

    
4
2013-09-21 16: 34: 34Z
  1. Большое спасибо за ваш ответ. Знаете ли вы, если я могу передать значение нового IP-адреса через переменную из Java-кода, например transformer.transform (xml, xslt, variable), поэтому я не буду указывать его непосредственно в файле xslt, поскольку значение вычисляется динамически?
    2011-01-13 01: 58: 38Z
  2. @ yart: Да. См. Саксонскую документацию здесь: saxonica.com/documentation/using-xsl/embedding. XML
    2011-01-13 02: 35: 07Z
источник размещен Вот