Use XML as database in Java

2020-03-26 08:12发布

I want to use XML file as database. Where I want to store an ID and its correspondingly a String path. Like:

<item>
     <Id>id</Id>
     <Path>path</Path>
</item> 

or like that. Now in runtime a Name-Value Collection will load this data stored in XML document and check the Id against some data and will be processed accordingly and also update (that is change path of same Id)and delete(removal of an existing item) of items is needed in that XML file. Hope I make you able to understand my idea! I have no code to show as this is in conceptual level. What I need is that how can I achieve this, is there any tutorial I can read or API available which is able to do this? Thank you. I am in JAVA.

标签: java xml
5条回答
贼婆χ
2楼-- · 2020-03-26 08:19

I'll assume this is actually a good idea for your application - that's a whole different discussion.

I would treat this as three separate problems:

  • Loading the XML file from disk and storing it in an appropriate data structure (such as a Map<String, String>)
  • Manipulating the collection appropriately (fetching, adding or removing entries)
  • Saving the XML file back to disk

Most of your code should probably be unaware that your collection will be stored in XML.

There are various XML APIs available for Java - the built-in ones tend to be quite a pain to use. I don't know what the latest and greatest ones are, but historically JDOM has proved fairly simple.

Note that your choice of in-memory collection will depend on your requirements - is the ordering important, for example?

查看更多
家丑人穷心不美
3楼-- · 2020-03-26 08:35

On the other hand you are closer to XML if you use XML-Database Systems, which offer XML database APIs. Like Exist or Apache Xindice.

查看更多
爷的心禁止访问
4楼-- · 2020-03-26 08:41

BaseX is a database XML, seams to deliver what you want to do!

http://basex.org/

查看更多
Viruses.
5楼-- · 2020-03-26 08:43

This will scale badly as you have to rewrite the whole XML file whenever you change the data. Just imagine you have 100000 entries and consider how much work you will have to do when using this database.

As a serialized form of an in-memory hashmap it is a different matter, though, as HashMap lookups are very fast. However, the easiest and fastest way to serialize a hashmap is to use the built-in XMLSerializer in the standard libraries.

查看更多
Explosion°爆炸
6楼-- · 2020-03-26 08:45

I prefer using Joox, a fluent api to manage dom in jquery like style. It has not dependencies, you can install with maven.

Just because java performance, It's better to use attributes than elements* (experience from coleages).

So I suggest you use your model in this way:

<items>
     <item id="1" path="path"/>
     ...
</items>

I created this class using Joox for you:

package test;
import static org.joox.JOOX.$;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.commons.io.FileUtils;
import org.joox.JOOX;
import org.joox.Match;
import org.xml.sax.SAXException;
    public class XmlDBTable{
        private Match dbMatch;
        private String xmlBeforeCommit;
        private boolean building;
        private String root;
        private String item;
        private String itemXpathTemplate;
        private File file;
        public void setRoot(String root){
            this.root=root;
        }
        public void setItemTemplate(String item){
            this.item=item;
        }
        public void setItemXpathTemplate(String itemXpath){
            this.itemXpathTemplate=itemXpath;
        }
        public void setFile(String path){
            file=new File(path);
            if(file.exists())
                try {
                    dbMatch=$(file);
                } catch (SAXException | IOException e) {
                    e.printStackTrace();
                }
        }
        public Match xml() {
            Match dbMatch= dbMatch();
            building=true;
            return dbMatch;
        }
        public void insertOrUpdate(String keyEqualsValueList){
            Match dbMatch= dbMatch();
            String newItem=item;
            if(keyEqualsValueList.contains(",")) {
                String[] keyValues=keyEqualsValueList.split(",");
                for(String keyValue:keyValues) {
                    String key=keyValue.split("=")[0].toUpperCase();
                    String value=keyValue.split("=")[1];
                    newItem=newItem.replace(key,value);
                }
            }else {
                String key=keyEqualsValueList.split("=")[0].toUpperCase();
                String value=keyEqualsValueList.split("=")[1];
                newItem=newItem.replace(key,value);
            }
            String id=itemId(newItem);
            String itemXpath=itemXpath(id);
            Match item=$(dbMatch).xpath(itemXpath);
            if ($(item).isEmpty()){
                $(dbMatch).append(newItem);
            }else{
                if(keyEqualsValueList.contains(",")) {
                    String[] keyValues=keyEqualsValueList.split(",");
                    for(String keyValue:keyValues) {
                        String key=keyValue.split("=")[0];
                        String value=keyValue.split("=")[1];
                        $(dbMatch).xpath(itemXpath).attr(key,value);
                    }
                }else {
                    String key=keyEqualsValueList.split("=")[0].toUpperCase();
                    String value=keyEqualsValueList.split("=")[1];
                    $(dbMatch).xpath(itemXpath).attr(key,value);
                }
            }
            building=true;
            System.out.println("Item id "+id+" added ok");
        }
        public void delete(String id){
            Match dbMatch= dbMatch();
            String itemXpath=itemXpath(id);
            Match item=$(dbMatch).xpath(itemXpath);
            if (!$(item).isEmpty()){
                $(dbMatch).xpath(itemXpath).remove();
                System.out.println("Item id "+id+" deleted ok");
            }else{
                System.out.println("The item didn't exist");
            }
            building=true;
        }
        private String itemId(String item) {
            String id=xmlStrToMatch(item, "UTF-8").attr("id");
            return id;
        }
        private String itemXpath(String id) {
            String itemXpath=itemXpathTemplate.replace("ID", id);
            return itemXpath;
        }
        public synchronized boolean commit(){
            try {
                FileUtils.writeStringToFile(file,dbMatch().toString(),"UTF-8");
                building=false;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return true;
        }
        public boolean rollBack(){
            dbMatch();
            dbMatch=xmlStrToMatch(xmlBeforeCommit, "UTF-8");
            System.out.println("Removed all changes after last commit");
            building=false;
            return true;
        }
        private Match dbMatch(){
            if(dbMatch==null){
                dbMatch=xmlStrToMatch(root,"UTF-8");
            }
            if(!building){
                if(xmlBeforeCommit!=null){
                    xmlBeforeCommit=dbMatch.toString();
                }else {
                    xmlBeforeCommit=root;
                }
            }
            return dbMatch;
        }
        private static Match xmlStrToMatch(String xmlString, String encoding){
            Match match = null;
            try {
                match = $(JOOX.builder().parse(new ByteArrayInputStream(xmlString.getBytes(encoding))));
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SAXException  e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return match;
        }
    }

To use it, you can use:

package test;

public class ItemsTable{
    public static void main(String... args){
        XmlDBTable itemsTable= new XmlDBTable();
        itemsTable.setRoot("<items></items>");
        itemsTable.setItemTemplate("<item id=\"ID\" path=\"PATH\"/>");
        itemsTable.setItemXpathTemplate("/items/item[@id='ID']");
        itemsTable.setFile("C:\\users\\jesus\\Downloads\\temp\\itemsTable.xml");
        itemsTable.insertOrUpdate("id=1,path=myPath");
        itemsTable.insertOrUpdate("id=2,path=myPath2");
        itemsTable.delete("2");
        itemsTable.insertOrUpdate("id=3,path=myPath3");
        //save changes
        itemsTable.commit();
        //you can use all power of Joox Methods too to do the same or more
        //Select path from item with id=1
        String path1=itemsTable.xml().xpath("//item[@id='1']").attr("path");
        //print it
        System.out.println(path1);
        //Add subItem id=0 to item with id=1
        itemsTable.xml().xpath("//item[@id='1']").append("<subitem id=\"0\" color=\"black\">Super Subitem</subitem>");
        //print the text of subitem recently added
        String subitem1=itemsTable.xml().xpath("//subitem[@id='0']").text();
        System.out.println(subitem1);
        //save changes
        itemsTable.commit();
        //Add subItem id=1 to item with id=1
        itemsTable.xml().xpath("//item[@id='1']").append("<subitem id=\"1\" color=\"blue\">Super Subitem</subitem>");
        //rollback changes after last commit (subitem id=1 in item id=1 deleted)
        itemsTable.rollBack();
        itemsTable.insertOrUpdate("id=4,path=myPath4");
        //save changes
        itemsTable.commit();
    }
}

*Please note that string templates use caps as default value,e.g. id="ID" *Another thing methods insertOrUpdate, and delete only works with attributes as columns. *You can use Joox methods to insert new lines, as shown.

This is the file produced:

<items>
    <item id="1" path="myPath">
        <subitem color="black" id="0">Super Subitem</subitem>
    </item>
    <item id="3" path="myPath3"/>
    <item id="4" path="myPath4"/>
</items>

This is the output in console:

Item id 2 added ok
Item id 2 deleted ok
Item id 3 added ok
myPath
Super Subitem
Removed all changes after last commit
Item id 4 added ok

My maven dependencies:

<dependency>
    <groupId>org.jooq</groupId>
    <artifactId>joox</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
</dependency>
查看更多
登录 后发表回答