Skip to content
/ pax Public

A pretty simple Data Passenger - building object trees by a tolerant XML reader

License

Notifications You must be signed in to change notification settings

graetz23/pax

Repository files navigation

PAX

A Java object tree implementation based on the Composite Pattern combined with a tolerant XML reader for reading and writing any Extensible Markup Language (XML) structure - no need for an XML Schema Definition XSD.

  ███████████    █████████   █████ █████
 ▒▒███▒▒▒▒▒███  ███▒▒▒▒▒███ ▒▒███ ▒▒███ 
  ▒███    ▒███ ▒███    ▒███  ▒▒███ ███  
  ▒██████████  ▒███████████   ▒▒█████   
  ▒███▒▒▒▒▒▒   ▒███▒▒▒▒▒███    ███▒███  
  ▒███         ▒███    ▒███   ███ ▒▒███ 
 █████        █████   █████ █████ █████
▒▒▒▒▒        ▒▒▒▒▒   ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ 

Introduction

Each created object can be stored as a node in a tree. There are no special types. Any object can start a fresh tree by being root. A root can store children. Those can be added or set. Any children can be fetched by tag or in case of many with the same name, by listing and filtering. Each object can also store attributes. Those are organized in the same way as child but are used as a list. By any object, the tree can be recursed and generated to any data format. Currently, the generation of XML is implemented only.

Installation

./gradlew build jar

Factory (Instances)

Get the factory to create new nodes:

IFactory factory = Instances.Factory();

produce(tag)

Create a new node with a tag name:

IPax root = Instances.Factory().produce("root");

produce(tag, val)

Create a new node with a tag and value:

IPax element = Instances.Factory().produce("title", "Effective Java");

copy(ipax)

Create a deep copy of an existing node:

IPax original = Instances.Factory().produce("book");
IPax copy = Instances.Factory().copy(original);

IPax Interface

All node operations are available through the IPax interface.

Tag Operations

Tag() - Get the tag name

IPax root = Instances.Factory().produce("book");
String tag = root.Tag(); // returns "book"

Tag(String tag) - Set the tag name

IPax root = Instances.Factory().produce("root");
root.Tag("book"); // changes tag to "book"

hasTag() - Check if tag exists

IPax node = Instances.Factory().produce("element");
boolean hasTag = node.hasTag(); // true

IPax noTag = Instances.Factory().produce(null);
boolean empty = noTag.hasTag(); // false

Value Operations

Val() - Get the value

IPax title = Instances.Factory().produce("title", "My Book");
String value = title.Val(); // returns "My Book"

Val(String val) - Set the value

IPax element = Instances.Factory().produce("description");
element.Val("A great book");

hasVal() - Check if value exists

IPax element = Instances.Factory().produce("empty");
boolean hasValue = element.hasVal(); // false

element.Val("content");
hasValue = element.hasVal(); // true

Note: Empty, blank, or newline-only values are rejected and stored as null.

Parent Operations

Parent() - Get the parent node

IPax parent = Instances.Factory().produce("parent");
IPax child = Instances.Factory().produce("child");
parent.Child().add(child);

IPax foundParent = child.Parent(); // returns parent

Parent(IPax parent) - Set the parent

IPax parent = Instances.Factory().produce("parent");
IPax child = Instances.Factory().produce("child");
child.Parent(parent);

hasParent() - Check if has parent

IPax root = Instances.Factory().produce("root");
boolean hasParent = root.hasParent(); // false

IPax child = Instances.Factory().produce("child");
root.Child().add(child);
hasParent = child.hasParent(); // true

Path Operations

Path() - Get the full path from root

IPax root = Instances.Factory().produce("library");
IPax book = Instances.Factory().produce("book");
root.Child().add(book);
IPax chapter = Instances.Factory().produce("chapter");
book.Child().add(chapter);

String path = chapter.Path(); // returns "/library/book/chapter"

Child Operations

Child() - Get children collection

IChildren children = root.Child();

hasChild() - Check if has children

boolean has = root.hasChild();

Attribute Operations

Attrib() - Get attributes collection

IAttributes attributes = root.Attrib();

hasAttrib() - Check if has attributes

boolean has = root.hasAttrib();

XML Generation

XML() - Generate XML with indentation

IPax root = Instances.Factory().produce("book");
root.Attrib().add("id", "1");
IPax title = Instances.Factory().produce("title", "Effective Java");
root.Child().add(title);

String xml = root.XML();
/*
<book id="1">
  <title>Effective Java</title>
</book>
*/

XML_lined() - Generate XML on single line

String xml = root.XML_lined(); // <book id="1"><title>Effective Java</title></book>

IChildren Interface

Manage child nodes.

add(String tag) - Add child by tag name

root.Child().add("chapter");

add(String tag, String val) - Add child with value

root.Child().add("author", "Joshua Bloch");

add(IPax child) - Add existing node as child

IPax chapter = Instances.Factory().produce("chapter", "Introduction");
root.Child().add(chapter);

get(String tag) - Get first child by tag

IPax chapter = root.Child().get("chapter");

get(int index) - Get child by index

IPax first = root.Child().get(0);

has(String tag) - Check if child exists

boolean exists = root.Child().has("chapter");

all() - Get all children

List<IPax> allChildren = root.Child().all();

all(String tag) - Get all children with specific tag

List<IPax> chapters = root.Child().all("chapter");

cnt() - Get children count

int count = root.Child().cnt();

del(String tag) - Delete first child by tag

root.Child().del("chapter");

del(IPax child) - Delete specific child

root.Child().del(chapter);

del() - Delete all children

root.Child().del();

set(String tag, String val) - Set or update child value

root.Child().set("title", "New Title");

set(IPax child) - Set or update child

root.Child().set(newChapter);

search(String path) - Search by XPath-like path

IPax found = root.Child().search("/library/book/chapter");
IPax foundRelative = root.Child().search("./book/chapter");

IAttributes Interface

Manage attributes on a node.

add(String tag, String val) - Add attribute

root.Attrib().add("id", "123");
root.Attrib().add("type", "novel");

add(IPax attribute) - Add attribute node

IPax attr = Instances.Factory().produce("class", "primary");
root.Attrib().add(attr);

get(String tag) - Get attribute by name

IPax id = root.Attrib().get("id");
String value = id.Val(); // "123"

has(String tag) - Check if attribute exists

boolean hasId = root.Attrib().has("id");

all() - Get all attributes

List<IPax> attrs = root.Attrib().all();

cnt() - Get attribute count

int count = root.Attrib().cnt();

del(String tag) - Delete attribute

root.Attrib().del("id");

del() - Delete all attributes

root.Attrib().del();

XML() - Generate attributes as XML string

String attrXml = root.Attrib().XML(); // returns "id=\"123\" type=\"novel\" "

Reader

Parse XML from various sources.

Reader.Instance - Get singleton instance

Reader reader = Reader.Instance;

parse(String filename) - Parse from file path

IPax root = Reader.Instance.parse("./config.xml");

parseLocalFile(String filename) - Parse local file

IPax root = Reader.Instance.parseLocalFile("data.xml");

stream(InputStream stream) - Parse from InputStream

String xml = "<book><title>Java</title></book>";
InputStream is = new ByteArrayInputStream(xml.getBytes());
IPax root = Reader.Instance.stream(is);

Writer

Write IPax trees to files.

Writer.Instance - Get singleton instance

Writer writer = Writer.Instance;

XML(IPax root) - Write to file using tag as filename

IPax book = Instances.Factory().produce("book");
book.Val("Content");
boolean success = Writer.Instance.XML(book); // writes to "book.xml"

XML(IPax root, String filename) - Write to specified file

boolean success = Writer.Instance.XML(book, "mybook.xml");
boolean success2 = Writer.Instance.XML(book, "output"); // adds .xml automatically

Complete Examples

Creating a Document

// Create root
IPax library = Instances.Factory().produce("library");

// Add attributes
library.Attrib().add("name", "City Library");
library.Attrib().add("location", "Downtown");

// Add children
IPax book1 = Instances.Factory().produce("book");
book1.Attrib().add("id", "1");
book1.Child().add("title", "Effective Java");
book1.Child().add("author", "Joshua Bloch");
library.Child().add(book1);

IPax book2 = Instances.Factory().produce("book");
book2.Attrib().add("id", "2");
book2.Child().add("title", "Clean Code");
book2.Child().add("author", "Robert Martin");
library.Child().add(book2);

// Generate XML
String xml = library.XML();
System.out.println(xml);

Output:

<library name="City Library" location="Downtown">
  <book id="1">
    <title>Effective Java</title>
    <author>Joshua Bloch</author>
  </book>
  <book id="2">
    <title>Clean Code</title>
    <author>Robert Martin</author>
  </book>
</library>

Reading and Modifying XML

// Read from file
IPax library = Reader.Instance.parse("library.xml");

// Find specific book using search
IPax book = library.Child().search("/library/book");

// Add new child
IPax review = Instances.Factory().produce("review", "Excellent!");
book.Child().add(review);

// Write back to file
Writer.Instance.XML(library, "library_updated.xml");

Copying Nodes

IPax original = Instances.Factory().produce("book");
original.Attrib().add("id", "1");
original.Child().add("title", "Original");

IPax copy = Instances.Factory().copy(original);
copy.Attrib().add("id", "2");
copy.Child().get("title").Val("Copy");

// Both nodes exist independently

Build

Gradle Wrapper is generated in version 9; try:

./gradlew build jar

If you need to settle another version of the wrapper, get the latest gradle version and install it.

The change to your cloned directory of jPAX and

gradle wrapper
./gradlew build

License

MIT License - See LICENSE file

Releases

No releases published

Packages

 
 
 

Contributors