0x04 Berkeley DB XMl Java版之添加 XML Document到Containers

宰父焕
2023-12-01

1. 添加 XML Document到Containers

要以BDB XML管理XML文档,必须将它们加载到容器中。 通常,我们将通过直接使用XmlContainer句柄来完成此操作。 我们还可以将文档加载到XmlDocument实例中,然后使用XmlContainer句柄将该实例加载到容器中。 本书主要使用第一种,最直接的方法。

1.1 输入流和字符串

将文档添加到容器时,必须标识文档所在的位置。 你可以通过使用:

  • 包含整个文档的字符串对象。
  • 从文件名创建的输入流。
    使用XmlManager.createLocalFileInputStream()创建输入流。
  • 从URL创建的输入流。
    在这种情况下,URL可以是任何有效的URL。 但是,如果URL需要网络活动才能访问标识的内容(例如,如果您提供HTTP URL,则需要),则只有在编译了具有套接字支持的Xerces时,输入流才有效。
    • 使用XmlManager.createURLInputStream()创建输入流。
  • 引用内存缓冲区的输入流。
    使用XmlManager.createMemBufInputStream()创建输入流。
  • 引用标准输入的输入流(Windows系统下的控制台)。
    使用XmlManager.createStdInInputStream()创建输入流

请注意,在我们实际尝试将文档放入容器之前,BDB XML不会验证输入流。
这意味着您可以创建到无效位置或无效内容的输入流,并且在您实际尝试从该位置加载数据之前,BDB XML不会引发异常。

我们在下一节中提供了创建输入流的示例。

1.2 添加 Documents

要将文档添加到容器,请使用XmlContainer.putDocument() 使用此方法时,您必须:

  • 以某种方式获取要放入容器的文档。
    为此,我们可以创建内容的输入流或将XML文档加载到字符串对象中。或者,我们可以将文档加载到XmlDocument对象中,然后将XmlDocument对象提供给XmlContainer.putDocument()。执行此操作时,可以使用输入流或字符串将文档提供给XmlDocument对象,也可以使用事件编写器构造文档。

  • 提供文档的名称。
    此名称必须是唯一的,否则BDB XML将抛XmlException.UNIQUE_ERROR
    如果使用XmlDocument对象添加文档,请使用XmlDocument.setName()设置文档的名称。否则,您可以直接在调用XmlContainer.putDocument()时设置名称。

    • 请注意,如果我们不想显式设置文档的名称,可以将XmlDocumentConfig.setGenerateName()设置为true,然后将该对象传递给XmlContainer.putDocument()。这会导致BDB XML为您生成唯一的名称。它生成的名称是唯一值,下划线和我们为文档名称提供的值的串联(如果有)。例如:myDocName_a
    • 其中myDocName是您为文档设置的名称,a是BDB XML生成的唯一值。
    • 如果没有为文档设置名称,但确实指定要生成唯一名称,则使用dbxml作为名称的前缀dbxml_b
    • 如果没有为文档设置名称,并且不使XmlDocumentConfig.setGenerateName(true),则BDB XML将抛出XmlException.UNIQUE_ERROR。

请注意,

  • 我们提供给XmlContainer.putDocument()的内容将被读取和验证。
  • 默认情况下,这包括文档可能引用的任何架构或DTD。 由于这会导致一些性能问题,因此可以使BDBXML仅通过XmlDocumentConfig.setWellFormedOnly() 设置为true来检查文档正文本身,然后将该对象传递XmlContainer.putDocument()
    但是,如果文档引用可能来自架构或DTD的信息,则使用此选项会导致解析错误。
  • 此外,请注意,虽然您的文档与其共享文本实体(如果有)一起存储在容器中,但基础XML解析器会尝试扩展它们以用于索引目的。
    因此,您必须确保文档中包含的任何实体在加载时都可以解析。

例如,要添加以字符串形式保存的文档:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlDocumentConfig;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlManager;

import java.io.FileNotFoundException;

public class doDbXml{
    public static void main(String args[]) {

        XmlManager myManager = null;
        XmlContainer myContainer = null;

         // The document
        String docString = "<a_node><b_node>Some text</b_node></a_node>";

        // The document's name.
        String docName = "testDoc1";

        try {
            myManager = new XmlManager();
            // Assumes the container currently exists.

            myContainer = myManager.openContainer("container.bdbxml");

            // Do the actual put
            myContainer.putDocument(docName,docString,new XmlDocumentConfig());

        } catch (XmlException e) {
            // Error handling goes here. You may want to check
            // for XmlException.UNIQUE_ERROR, which is raised
            // if a document with that name already exists in
            // the container. If this exception is thrown,
            // try the put again with a different name.
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (myContainer != null) {
                    myContainer.close();
                }

                if (myManager != null) {
                    myManager.close();
                }
            } catch (XmlException ce) {
                // Exception handling goes here
            }
        }
    }
}

要从输入流加载文档,除了在XmlManager上使用适当的方法获取流之外,代码是相同的。 例如,要直接从磁盘上的文件加载XmlDocument:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.*;

import java.io.FileNotFoundException;

public class doDbXml {
    public static void main(String args[]) {

        XmlManager myManager = null;
        XmlContainer myContainer = null;

         // The document
        String fileName= "/export/testdoc1.xml";

        // The document's name.
        String docName = "testDoc1";
        try {
            myManager = new XmlManager();
            // Assumes the container currently exists.

            myContainer = myManager.openContainer("container.bdbxml");

            // Get the input stream.
            XmlInputStream theStream = myManager.createLocalFileInputStream(fileName);

            // Do the actual put
            myContainer.putDocument(docName,     // The document's name
                    theStream,   // The actual document.
                    new XmlDocumentConfig());       // XmlDocumentConfig object
        } catch (XmlException e) {
            // Error handling goes here. You may want to check
            // for XmlException.UNIQUE_ERROR, which is raised
            // if a document with that name already exists in
            // the container. If this exception is thrown,
            // try the put again with a different name.
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (myContainer != null) {
                    myContainer.close();
                }

                if (myManager != null) {
                    myManager.close();
                }
            } catch (XmlException ce) {
                // Exception handling goes here
            }
        }
    }
}

1.3 使用事件编写器构造文档

在上一节中,我们展示了如何通过从磁盘读取文档或将文档作为字符串对象提供,将文档加载到容器中。 或者,我们可以使用XmlEventWriter类对象构造文档,该对象将文档存储在XmlDocument对象中。 然后,您可以将该XmlDocument对象放入容器,如上一节中所述。

XmlEventWriter提供的方法允许您描述文档的各个离散部分。 例如,如果您已经使用SAX解析器解析文档并且希望将解析器发现的信息写入容器,那么它很有用。

要使用事件编写器

  1. 创建XmlDocument实例。

  2. 使用XmlDocument.setName()方法为其命名。

  3. 使用XmlContainer.putDocumentAsEventWriter()方法将文档放入容器中。请注意,此时您实际上没有将任何文档数据写入容器,因为您的文档当前是空的。

此方法返回XmlEventWriter对象。

  1. 使用XmlEventWriter对象启动新文档。
    您可以使用XmlEventWriter.writeStartDocument()方法执行此操作,该方法允许您描述有关XML文档的信息,例如其编码及其XML版本标识。

  2. 启动文档后,您可以编写开始和结束元素,属性,处理指令,文本,CDATA以及您可能希望放在XML文档上的所有其他功能。 XmlEventWriter提供了允许您执行这些操作的方法。

  3. 完成文档后,使用XmlEventWriter.close()方法关闭它。这样就完成了您在步骤3中开始的容器放置操作。

例如,假设您要将以下文档写入容器:

<a>
<b a1="one" b2="two">b node text</b>
<c>c node text</c>
</a> 

然后,以下代码片段将完成该任务:

 // Manager and container opens omitted for brevity.

         // create a new document
         XmlDocument doc = mgr.createDocument();
         doc.setName(dname);

         XmlEventWriter writer = 
            container.putDocumentAsEventWriter(doc);
         writer.writeStartDocument(null, null, null); // no XML decl

        // Write the document's root node. It has no prefixes or
        // attributes. This node is not empty.
        writer.writeStartElement("a", null, null, 0, false);

        // Write a new start element. This time for the "b" node.
        // It has two attributes and its content is also not empty.
        writer.writeStartElement("b", null, null, 2, false);
        // Write the "a1" and "b2" attributes on the "b" node
        writer.writeAttribute("a1", null, null, "one", true);
        writer.writeAttribute("b2", null, null, "two", true);
        // Write the "b" node's content. Note that there are 11
        // characters in this text, and we provide that information
        // to the method.
        writer.writeText(XmlManager.Characters, "b node text", 11);
        // End the "b" node
        writer.writeEndElement("b", null, null);
        // Start the "c" node. There are no attributes on this node.
        writer.writeStartElement("c", null, null, 0, false);
        // Write the "c" node's content
        writer.writeText(XmlManager.Characters, "c node text", 11);
        // End the "c" node and then the "a" (the root) node
        writer.writeEndElement("c", null, null);
        writer.writeEndElement("a", null, null);

        // End the document
        writer.writeEndDocument();
        // Close the document
        writer.close(); 

1.4 设置元数据

存储在BDB XML中的每个XML文档实际上都包含两种信息:文档本身和元数据。

Metadata(元数据)可以包含任意复杂的信息集。通常,它包含有关您未在文档中包含或不包含在文档中的文档的信息。例如,您可以携带有关将文档添加到容器,上次修改或可能是到期时间的日期和时间的信息。元数据还可用于存储有关BDB XML外部文档的信息,例如最初存储文档的磁盘上位置,或者可能包含有关文档维护者可能有用的文档的注释。

换句话说,元数据可以包含任何内容–BDB XML对您可以使用它的内容没有任何限制。此外,您可以查询和索引元数据(有关更多信息,请参阅使用BDB XML索引)。甚至可以在容器中包含仅包含元数据的文档。

要将元数据设置到文档中,您必须:

  1. (可选)(但建议)为每条元数据(以字符串形式)创建URI

  2. 创建一个用于元数据的属性名称,同样以字符串的形式。

  3. 创建属性值 - 要在文档上携带的实际元数据信息 - 作为XmlValue或作为Java byte[]数组。

  4. XmlDocument对象上设置此信息。

  5. (可选)(但通常)将实际的XML文档设置为相同的XmlDocument对象。

  6. 将XmlDocument添加到容器中。

package dbxml.gettingStarted;

import com.sleepycat.dbxml.*;

import java.io.FileNotFoundException;

public class doDbXml {
    public static void main(String args[]) {

        XmlManager myManager = null;
        XmlContainer myContainer = null;

        // The document
        String fileName = "/export/testdoc1.xml";

        // The document's name.
        String docName = "testDoc1";

        try {
            // URI, attribute name, and attribute value used for
            // the metadata. We will carry a timestamp here
            // (hard coded for clarity purposes).
            String URI = "http://dbxmlExamples/metadata";
            String attrName = "createdOn";
            XmlValue attrValue =
                    new XmlValue(XmlValue.DATE_TIME, "2005-10-5T04:18:36");

            myManager = new XmlManager();
            // Assumes the container currently exists.

            myContainer =
                    myManager.openContainer("container.bdbxml");

            // Get the input stream.
            XmlInputStream theStream = myManager.createLocalFileInputStream(fileName);

            // Get an XmlDocument
            XmlDocument myDoc = myManager.createDocument();

            // Set the document's name
            myDoc.setName(docName);
            // Set the content
            myDoc.setContentAsXmlInputStream(theStream);
            // Set the metadata
            myDoc.setMetaData(URI, attrName, attrValue);

            // Put the document into the container
            myContainer.putDocument(myDoc,        // The actual document.
                    new XmlDocumentConfig());       // XmlDocumentConfig object
        } catch (XmlException e) {
            // Error handling goes here. You may want to check
            // for XmlException.UNIQUE_ERROR, which is raised
            // if a document with that name already exists in
            // the container. If this exception is thrown,
            // try the put again with a different name.
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (myContainer != null) {
                    myContainer.close();
                }

                if (myManager != null) {
                    myManager.close();
                }
            } catch (XmlException ce) {
                // Exception handling goes here
            }
        }
    }
}


最近公司要忙其他技术方向了,暂时停止这方面博文更新。

如果有喜欢这方面博文的道友,请留言,只要有一个喜欢我就把它更新完~

之前这几章内容,总结了一个Demo ,有需要的可以拿去。
https://github.com/geekxingyun/Oracle-Berkeley-DB/tree/master/berkeleydbxmlsample

 类似资料: