java - 使用保持格式的 DOM 在 XML 中追加元素

标签 java xml parsing dom

我有一个这样的xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Empleado>
  <ConsultorTecnico>
    <Nombre>Pablo</Nombre>
    <Legajo antiguedad="4 meses">7778</Legajo>
  </ConsultorTecnico>
  <CNC>
    <Nombre>Brian</Nombre>
    <Legajo antiguedad="1 año, 7 meses">2134</Legajo>
  <Sueldo>4268.0</Sueldo>
  </CNC>
</Empleado>

我想要的是读取 XML 并在元素“CNC”中附加与“Nombre”和“Legajo”相同级别的“Sueldo”。 “Sueldo”必须是“Legajo”x 2

我的代码附加了“Sueldo”,正如您在上面的 XML 中看到的那样,但它没有按应有的方式缩进,我使用属性来缩进(此 XML 的创建方式相同,使用 DOM)

public class Main
{
    public static void main(String[] args)
    {
        try
        {
          File xml = new File("C:\\Empleado.xml");
          if (xml.exists() == true)
          {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(xml);

            String legajo = doc.getElementsByTagName("Legajo").item(1).getFirstChild().getNodeValue();

        Element sueldo = doc.createElement("Sueldo");
        Node valorSueldo = doc.createTextNode(String.valueOf(Float.valueOf(legajo)*2));
        sueldo.appendChild(valorSueldo);

        Node cnc = doc.getElementsByTagName("CNC").item(0);

        cnc.appendChild(sueldo);

        DOMSource source = new DOMSource(doc);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();

        t.setOutputProperty(OutputKeys.INDENT, "yes");
        t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","2"); 

        FileOutputStream fos = new FileOutputStream("C:\\Empleado.xml");
        StreamResult sr = new StreamResult(fos);

        t.transform(source,sr);    

        }
      else
          throw new Exception("No hay archivo XML con ese nombre en el directorio");
    }
    catch (Exception e) 
    {
      System.out.println(e.getMessage());
    }
}

提前谢谢你们,我会很感激这里的帮助!

最佳答案

假设您的输入文件与您显示的输出相同,但没有 Sueldo元素,然后是初始的 CNC就 DOM 而言,元素有 五个 个子节点

  • <CNC> 之间的空白文本节点(换行符和四个空格)和 <Nombre>
  • Nombre元素节点
  • </Nombre> 之间的空白文本节点(换行符和四个空格)和 <Legajo
  • Legajo元素节点
  • </Legajo> 之间的空白文本节点(换行符和两个 空格)和 </CNC>

您正在插入 Sueldo最终文本节点之后的元素,它产生

  <CNC>
    <Nombre>Brian</Nombre>
    <Legajo antiguedad="1 año, 7 meses">2134</Legajo>
  <Sueldo>4268.0</Sueldo></CNC>

INDENT output 属性只是移动结束 </CNC>标记到下一行,与开头的一行对齐。要让自动缩进做正确的事情,您需要从初始树中删除所有纯空白文本节点。

或者,忘记自动缩进并自己做 - 而不是添加 Sueldo作为 CNC最后一个 child (在最后一个文本节点之后),而是在 Legajo 之后立即添加一个换行符和四个空格的文本节点。 (即在最后一个文本节点之前)然后添加 Sueldo之后的元素。


作为完全替代的方法,我会考虑在 XSLT 中进行转换而不是使用 DOM API

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <!-- ignore whitespace-only text nodes in the input -->
  <xsl:strip-space elements="*"/>
  <!-- and re-indent the output -->
  <xsl:output method="xml" indent="yes" />

  <!-- Copy everything verbatim except where otherwise specified -->
  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>

  <!-- For CNC elements, add a Sueldo as the last child -->
  <xsl:template match="CNC">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
      <Sueldo><xsl:value-of select="Legajo * 2" /></Sueldo>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

您可以使用 TransformerFactory 运行它来自 Java 代码或使用独立命令行 XSLT 处理器的 API。

关于java - 使用保持格式的 DOM 在 XML 中追加元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18407321/

相关文章:

java - 将servlet连接到数据库as400

java - Httpclient 未正确缓存响应

java - 在 eclipse 中运行 jbehave 测试时出现 org.jbehave.core.io.storyresourcenotfound 异常

java - 如何使用java通过HttpPost发送空的二进制数据

c++ - 非常复杂的软件的合理配置方法?

c# - 来自 Windows Phone 8 的 XML HTTP Post 请求

c# - XmlTextReader 问题

python - 使用 Pandas 库将历史 Metatrader CSV 数据导入 Python(日期/时间解析)

r - 如何将 data.frame 解析为树?

ios - 在 iOS 中是否有将 IP 地址解析为 4 个整数的函数?