在 Java 中使用 XML 作为数据库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4842813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:17:41  来源:igfitidea点击:

Use XML as database in Java

javaxml

提问by Tapas Bose

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

我想使用 XML 文件作为数据库。我想在哪里存储 ID 及其相应的字符串路径。喜欢:

<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.

或者像那样。现在在运行时,名称-值集合将加载存储在 XML 文档中的这些数据,并根据某些数据检查 Id,并将进行相应处理,并更新(即更改相同 Id 的路径)和删除(删除现有项目)该 XML 文件中需要项目。希望我能让你明白我的想法!我没有代码可以显示,因为这是在概念级别。我需要的是如何实现这一点,是否有任何我可以阅读的教程或可用的 API 能够做到这一点?谢谢你。我在JAVA。

回答by Costis Aivalis

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

另一方面,如果您使用提供 XML 数据库 API 的 XML 数据库系统,则您更接近 XML。像ExistApache Xindice

回答by Jon Skeet

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
  • 从磁盘加载 XML 文件并将其存储在适当的数据结构中(例如Map<String, String>
  • 适当地操作集合(获取、添加或删除条目)
  • 将 XML 文件保存回磁盘

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

您的大部分代码可能不知道您的集合将存储在 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 JDOMhas proved fairly simple.

有各种可用于 Java 的 XML API - 内置的 API 使用起来很麻烦。我不知道最新和最伟大的是什么,但从历史上看,JDOM已经证明相当简单。

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

请注意,您对内存中集合的选择将取决于您的要求 - 例如,排序是否重要?

回答by Thorbj?rn Ravn Andersen

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.

这将很糟糕,因为无论何时更改数据都必须重写整个 XML 文件。想象一下,您有 100000 个条目,并考虑在使用此数据库时需要做多少工作。

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.

但是,作为内存中哈希图的序列化形式,这是另一回事,因为 HashMap 查找非常快。但是,序列化哈希图的最简单和最快的方法是使用标准库中的内置 XMLSerializer。

回答by LottaLava

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

BaseX 是一个数据库 XML,接缝交付您想做的事!

http://basex.org/

http://basex.org/

回答by jechaviz

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

我更喜欢使用Joox,一个流畅的 api 来管理像 jquery 风格的 dom。它没有依赖项,您可以使用 maven 安装。

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

仅仅因为java性能,使用属性比使用元素*更好(来自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:

我使用 Joox 为您创建了这个类:

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.

*请注意,字符串模板使用大写字母作为默认值,例如 id="ID" *另一个方法 insertOrUpdate 和 delete 仅适用于作为列的属性。*您可以使用 Joox 方法插入新行,如图所示。

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:

我的 Maven 依赖项:

<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>