3

我有一个这样的 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 并将“Sueldo”附加到与元素“CNC”中的“Nombre”和“Legajo”相同的级别。“Sueldo”必须是“Legajo” x 2

正如您在上面的 XML 中看到的那样,我的代码附加了“Sueldo”,但它没有按应有的方式缩进,我使用属性来缩进(这个 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());
    }
}

}

提前谢谢你们,我将在这里感谢您的帮助!

4

2 回答 2

1

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

  • <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输出属性只是将结束</CNC>标签移动到下一行,与开始标签对齐。为了让自动缩进做正确的事情,您需要从初始树中删除所有仅空白文本节点。

或者,忘记自动缩进并自己做 - 而不是添加Sueldo为(在最终文本节点之后)的最后一个子节点,而是在之后(即在最后一个文本节点之前CNC)立即添加一个换行符和四个空格的文本节点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>

您可以使用TransformerFactoryJava 代码中的 API 或使用独立的命令行 XSLT 处理器运行它。

于 2013-08-23T16:25:26.417 回答
0

XML 本质上没有定义任何缩进或漂亮的形式。如果您希望它“缩进”,则需要插入带有换行符和空格的内容。在这种情况下,您需要紧跟在 element 之后Legajo和 element 之前的内容Sueldo

根据我的口味,最好的策略是忽略XML 文件中的所有格式,并在人类消费之前立即使用通用的美化器。或者,更好的是,给他们好的 XML 编辑器。如果您让每个操作 XML 文件的程序都关心这个细节,那么 XML 的大部分好处都没有了(并且大量的努力被滥用了)。

更新:刚刚注意到您正在使用元素CNC来“定位”插入,而不是Legajo. 空格和换行符内容需要紧挨在 element 之前CNC(和 element 之后Sueldo)。

于 2013-08-23T16:19:16.953 回答