在XML文件中添加新节点

时间:2014-06-13 08:43:37

标签: java xml xpath xml-parsing

我有一个xml文件,其结构如下:

<?xml version="1.0"?>
<entries>
  <entry accente="one">
    <list>Word</list>
    <sense class="0" value="B">
      <definition>
        <MorfDef>s. m.</MorfDef>
        <RegDef>This <i>text</i> have i node.</RegDef>
        <ItalMarker>Text.</ItalMarker>
      </definition>
    </sense>
   </entry>
  <entry accente="two">
    <list>B  n-1</list>
    <sense class="0" value="B">
      <definition>
        <MorfDef>s. m.</MorfDef>
        <RegDef>This text doesn't have i atribute.</RegDef>
        <ItalMarker>Word.</ItalMarker>
      </definition>
    </sense>
   </entry>
</entries>

我想为RegDef元素中的每个单词添加一个新节点,结果可能是:

<?xml version="1.0"?>
<entries>
  <entry accente="one">
    <list>Word</list>
    <sense class="0" value="B">
      <definition>
        <MorfDef>s. m.</MorfDef>
        <RegDef><w lemma="A1">This</w> <i><w lemma="A2">text</w></i> <w lemma="A3">have</w> <w lemma="A4">i</w> <w lemma="A5">node</w> <w lemma="A6">.</w></RegDef>
        <ItalMarker>Text.</ItalMarker>
      </definition>
    </sense>
   </entry>
  <entry accente="two">
    <list>B  n-1</list>
    <sense class="0" value="B">
      <definition>
        <MorfDef>s. m.</MorfDef>
        <RegDef><w lemma="A7">This</w> <w lemma="A8">text</w> <w lemma="A8">doesn't</w> <w lemma="A10">have</w> <w lemma="A11">i</w> <w lemma="A12">atribute</w> <w lemma="A13">.</w></RegDef>
        <ItalMarker>Word.</ItalMarker>
      </definition>
    </sense>
   </entry>
</entries>

如果RegDef节点具有&lt;我&gt;节点我想读取&lt;我&gt;节点并写一个&lt; w>每个单词的节点。 我尝试使用XPath,如下所示:

 Element rootElement = document.getDocumentElement();
Element element = document.createElement("w");
rootElement.appendChild(element);

但它紧跟在根节点之后。如何为RegDef标记中的每个单词编写一个节点,然后向该节点添加一个属性? 谢谢。

1 个答案:

答案 0 :(得分:1)

您选择了文件<entries> root 节点。如果在该节点上使用appendChild,则您的节点将作为根节点的 last 子节点附加,这是预期的行为。

您实际上希望使用RegDef元素在w节点内换行单词,这不是一个简单的任务,就像您在其中包含的三行代码一样简单例。

为此你需要:

  1. 选择该节点(DOM中有许多方法,document.getElementsByTagName("RegDef")将为您提供包含所有这些方法的NodeList。您也可以使用XPath。
  2. 对于每个RegDef,您需要选择其所有后代文本节点。如果您使用XPath,则在每个.//text() 的上下文中使用RegDef 等表达式将为您提供这些节点的列表。每个人可能包含一个或多个“单词”,甚至包含空格和换行符。
  3. 您可以通过按空格或标点符号或其他可用作的分隔符的字符进行拆分来提取单词。 Java中有几种工具,包括正则表达式。
  4. 最后,当您隔离了每个单词“word”并删除了要忽略的节点时,您可以为每个节点创建一个w元素,创建一个新的包含单词的文本节点将文本节点追加作为该元素的子节点。您还必须设置属性。
  5. 也许您应该使用较小的XML文件来关注您的特定问题,然后将其调整为您的真实示例。你可以从这样的事情开始:

    String xml = "<nodes>\n"
            + "    <RegDef>This <i>text</i> have i node.</RegDef>\n"
            + "    <RegDef>This text doesn't have i atribute.</RegDef>\n"
            + "</nodes>";
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = dbf.newDocumentBuilder();
    Document document = builder.parse(new InputSource(new StringReader(xml)));
    
    NodeList regDefNodes = document.getElementsByTagName("RegDef");
    int size = regDefNodes.getLength();
    for(int i = 0; i < size; i++) {
        Element regDef = (Element)regDefNodes.item(i);
        Element newRegDef = wrapWordsInContents(regDef, document);
        Element parent = (Element)regDef.getParentNode();
        parent.replaceChild(newRegDef, regDef);
    }
    

    现在,您可以使用上述步骤作为指南,并编写wrapWordsInContents(Element e, Document doc)方法。

    更新:您询问是否在包含wrapWordsInContents(Element e, Document doc)方法的 followup question 中对内容进行了标记。在调用该方法并使用以下代码序列化上面的代码之后:

    Transformer t = TransformerFactory.newInstance().newTransformer();
    t.transform(new DOMSource(document), new StreamResult(System.out));
    

    您将获得与您期望的结果类似的结果。请参阅您的后续问题:Modify the text content of XML tag