如何将新节点插入现有XML

时间:2013-05-18 06:28:33

标签: android xml

我想在现有的xml文件中插入一个新节点,但下面的代码会再次插入所有节点。

如果文件存在,我会进行测试。如果没有,我创建一个新的xml文件并编写标签。如果存在,它也会创建节点,但方法错误。

//create a new file called "new.xml" in the SD card
File newxmlfile = new File(Environment.getExternalStorageDirectory() + "/download/teste/audit.xml");

if (newxmlfile.exists()){

    try{
        fileos = new FileOutputStream(newxmlfile, true);
    }catch(FileNotFoundException e){
        Log.e("FileNotFoundException", "can't create FileOutputStream");
    }


} else {                    

    try{
        newxmlfile.createNewFile();
    }catch(IOException e){
        Log.e("IOException", "exception in createNewFile() method");
    }

    try{
        fileos = new FileOutputStream(newxmlfile);
    }catch(FileNotFoundException e){
        Log.e("FileNotFoundException", "can't create FileOutputStream");
    }
}

//we create a XmlSerializer in order to write xml data
XmlSerializer serializer = Xml.newSerializer();
try {
    serializer.setOutput(fileos, "UTF-8");
    serializer.startDocument(null, Boolean.valueOf(true));
    serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);

    serializer.startTag(null, "root");
        serializer.startTag(null, "child1");
        serializer.endTag(null, "child1");

        serializer.startTag(null, "child2");
        serializer.attribute(null, "attribute", "value");
        serializer.endTag(null, "child2");

            serializer.startTag(null, "child3");
        serializer.text("some text inside child3");
        serializer.endTag(null, "child3");                           
    serializer.endTag(null, "root");
    serializer.endDocument();
    serializer.flush();
    fileos.close();

    Context context = getApplicationContext();
    CharSequence text = "Save!";
    int duration = Toast.LENGTH_SHORT;
    Toast toast = Toast.makeText(context, text, duration);
    toast.show();

} catch (Exception e) {
    Log.e("Exception","error occurred while creating xml file");
}

结果如下:

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<root>
  <child1 />
  <child2 attribute="value" />
  <child3>some text inside child3</child3>
</root><?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<root>
  <child1 />
  <child2 attribute="value" />
  <child3>some text inside child3</child3>
</root>

但我希望结果如下:

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<root>
  <child1 />
  <child2 attribute="value" />
  <child3>some text inside child3</child3>
  <child1 />
  <child2 attribute="value" />
  <child3>some text inside child3</child3>
</root>

谢谢!

1 个答案:

答案 0 :(得分:1)

看起来Android中没有这样的API。但是,您仍有以下选项可以解决此问题:

  • 寻找一些提供这种能力的开源库;
  • 仍然使用XmlSerializer进行一些手动字符串操作,如下所示:

    private void testXMLFiles() {
        //create a new file called "new.xml" in the SD card
        final File newXmlFile = new File(Environment.getExternalStorageDirectory() + "/download/teste/audit.xml");
        RandomAccessFile randomAccessFile = null;
        final boolean fileExists = newXmlFile.exists();
        String lastLine = null;
    
        if (fileExists) {
            try {
                randomAccessFile = new RandomAccessFile(newXmlFile, "rw");
                randomAccessFile.seek(0);
    
                if (null != randomAccessFile) {
                    final Scanner scanner = new Scanner(newXmlFile);
                    int lastLineOffset = 0;
                    int lastLineLength = 0;
    
                    while (scanner.hasNextLine()) {
                        // +1 is for end line symbol
                        lastLine = scanner.nextLine();
                        lastLineLength = lastLine.length() + 2;
                        lastLineOffset += lastLineLength;
                    }
    
                    // don't need last </root> line offset
                    lastLineOffset -= lastLineLength;
    
                    // got to string before last
                    randomAccessFile.seek(lastLineOffset);
                }
            } catch(FileNotFoundException e) {
                Log.e("FileNotFoundException", "can't create FileOutputStream");
            } catch (IOException e) {
                Log.e("IOException", "Failed to find last line");
            }
        } else {
            try {
                newXmlFile.createNewFile();
            } catch(IOException e) {
                Log.e("IOException", "exception in createNewFile() method");
            }
    
            try {
                randomAccessFile = new RandomAccessFile(newXmlFile, "rw");
            } catch(FileNotFoundException e) {
                Log.e("FileNotFoundException", "can't create FileOutputStream");
            }
        }
    
        //we create a XmlSerializer in order to write xml data
        XmlSerializer serializer = Xml.newSerializer();
    
        if (randomAccessFile == null) {
            return;
        }
    
        try {
            final StringWriter writer = new StringWriter();
    
            serializer.setOutput(writer);
    
            if (!fileExists) {
                serializer.startDocument(null, true);
                serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
                serializer.startTag(null, "root");
            } else {
                serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
            }
    
            serializer.startTag(null, "child1");
            serializer.endTag(null, "child1");
    
            serializer.startTag(null, "child2");
            serializer.attribute(null, "attribute", "value");
            serializer.endTag(null, "child2");
    
            serializer.startTag(null, "child3");
            serializer.text("some text inside child3");
            serializer.endTag(null, "child3");
    
            if (!fileExists) {
                serializer.endTag(null, "root");
            }
    
            serializer.flush();
    
            if (lastLine != null) {
                serializer.endDocument();
                writer.append(lastLine);
            }
    
            // Add \n just for better output in console
            randomAccessFile.writeBytes(writer.toString() + "\n");
            randomAccessFile.close();
    
            Toast.makeText(getApplicationContext(), "Save!", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            Log.e("Exception","error occurred while creating xml file");
            e.printStackTrace();
        }
    }
    

第二次运行后的输出如下(非常类似于您的预期):

<?xml version='1.0' standalone='yes' ?>
<root>
  <child1 />
  <child2 attribute="value" />
  <child3>some text inside child3</child3>

<child1 />
<child2 attribute="value" />
<child3>some text inside child3</child3></root>
  • 存储来自初始xml的所有代码(例如,使用SAXParser您可以读取代码,同时写入新文件并使用XMLSerializer)在最后添加新文件;