Update: this didn't actually work. It looks right when serialized, but the in-memory DOM doesn't have the correct Element implementation. I ended up writing a new NSDOMBuilder class.
import groovy.xml.DOMBuilder
import groovy.xml.QName
import javax.xml.XMLConstants
import org.w3c.dom.Element
import org.joda.time.format.DateTimeFormatter
import org.joda.time.format.ISODateTimeFormat
DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTimeNoMillis()
def builder = DOMBuilder.newInstance()
def now = new DateTime()
Element el = builder.'ebiz:GetInventoryConsumption'(releaseID:'9.0',
xmlns:[(new QName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, 'xmlns')):'http://www.openapplications.org/oagis/9',
(new QName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, 'xmlns:ebiz')):'http://www.dis-corp.com/xml/ebusiness/2.0']) {
ApplicationArea() {
Sender(InetAddress.getLocalHost().getHostName())
CreationDateTime(dateTimeFormatter.print(now))
BODID(UUID.randomUUID())
}
DataArea() {
Get() {
Expression()
}
InventoryConsumption() {
'ebiz:InventoryConsumptionHeader'() {
// stuff goes here
}
}
}
}
Update 2. Here's the actual code:
HashMapStack.java
package groovy.xml;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
public class HashMapStack
implements Map
{
private LinkedList stack = new LinkedList();
public HashMapStack()
{
stack.add(new HashMap());
}
/**
* Clears the whole structure.
*/
public void clear()
{
stack.clear();
stack.add(new HashMap());
}
public boolean containsKey(Object key)
{
for (ListIterator iter = stack.listIterator(stack.size()); iter.hasPrevious();)
{
Map map = (Map) iter.previous();
if (map.containsKey(key))
{
return true;
}
}
return false;
}
public boolean containsValue(Object value)
{
for (ListIterator iter = stack.listIterator(stack.size()); iter.hasPrevious();)
{
Map map = (Map) iter.previous();
if (map.containsValue(value))
{
return true;
}
}
return false;
}
public Set entrySet()
{
throw new UnsupportedOperationException();
}
public Object get(Object key)
{
for (ListIterator iter = stack.listIterator(stack.size()); iter.hasPrevious();)
{
Map map = (Map) iter.previous();
if (map.containsKey(key))
{
return map.get(key);
}
}
return null;
}
public boolean isEmpty()
{
return false;
}
public Set keySet()
{
HashSet set = new HashSet();
for (Iterator iter = stack.iterator(); iter.hasNext();)
{
Map map = (Map) iter.next();
set.addAll(map.keySet());
}
return set;
}
/**
* Only returns the value of the item replaced in the current frame, not in any lower frames.
*/
public Object put(Object key, Object value)
{
return ((Map) stack.getLast()).put(key, value);
}
public void putAll(Map t)
{
((Map) stack.getLast()).putAll(t);
}
/**
* Only removes the key from the current frame.
*/
public Object remove(Object key)
{
return ((Map) stack.getLast()).remove(key);
}
public int size()
{
return keySet().size();
}
public Collection values()
{
throw new UnsupportedOperationException();
}
public void push()
{
stack.add(new HashMap());
}
public void pop()
{
if (stack.size() > 1)
{
stack.removeLast();
}
else
{
throw new IndexOutOfBoundsException();
}
}
}
NSDOMBuilder.groovy
package groovy.xml
import javax.xml.namespace.QName
import groovy.xml.FactorySupport
import javax.xml.namespace.QName
import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.parsers.ParserConfigurationException
import org.w3c.dom.Document
import org.w3c.dom.Element
import org.w3c.dom.Node
import org.xml.sax.InputSource
import org.xml.sax.SAXException
class NSDOMBuilder extends BuilderSupport {
private boolean namespaceAware
private HashMapStack nsMap = new HashMapStack()
private Document document
private DocumentBuilder documentBuilder
static NSDOMBuilder newInstance() throws ParserConfigurationException {
return newInstance(false, true)
}
static NSDOMBuilder newInstance(boolean validating, boolean namespaceAware) throws ParserConfigurationException {
DocumentBuilderFactory factory = FactorySupport.createDocumentBuilderFactory()
factory.setNamespaceAware(namespaceAware)
factory.setValidating(validating)
return new NSDOMBuilder(factory.newDocumentBuilder())
}
static Document parse(Reader reader) throws SAXException, IOException, ParserConfigurationException {
return parse(reader, false, true)
}
static Document parse(Reader reader, boolean validating, boolean namespaceAware)
throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = FactorySupport.createDocumentBuilderFactory()
factory.setNamespaceAware(namespaceAware)
factory.setValidating(validating)
DocumentBuilder documentBuilder = factory.newDocumentBuilder()
return documentBuilder.parse(new InputSource(reader))
}
NSDOMBuilder(Document document) {
this(document, true)
}
NSDOMBuilder(Document document, boolean namespaceAware) {
this.document = document
this.namespaceAware = namespaceAware
}
NSDOMBuilder(DocumentBuilder documentBuilder) {
this.documentBuilder = documentBuilder
this.namespaceAware = documentBuilder.namespaceAware
}
protected void setParent(Object parent, Object child) {
Node current = (Node) parent
Node node = (Node) child
current.appendChild(node)
}
protected Object createNode(Object name) {
return createNode(name, [:])
}
protected Document createDocument() {
if (documentBuilder == null) {
throw new IllegalArgumentException("No Document or DOMImplementation available so cannot create Document")
} else {
return documentBuilder.newDocument()
}
}
protected Object createNode(Object name, Object value) {
Element element = (Element) createNode(name, [:])
element.appendChild(document.createTextNode(value.toString()))
return element
}
protected Object createNode(Object name, Map attributes, Object value) {
Element element = (Element) createNode(name, attributes)
element.appendChild(document.createTextNode(value.toString()))
return element
}
protected Object createNode(Object name, Map attributes) {
if (namespaceAware) {
nsMap.push()
for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
def entry = iter.next()
String attrName = entry.key.toString()
if ("xmlns".equals(attrName) || attrName.startsWith("xmlns:")) {
String prefix = ''
if (attrName.startsWith("xmlns:")) {
prefix = attrName.substring(6)
}
nsMap.put(prefix, entry.value)
iter.remove()
}
}
}
if (document == null) {
document = createDocument()
}
Element element
if (namespaceAware) {
def qname = parseQName(name)
element = document.createElementNS(qname.namespaceURI, name)
} else {
element = document.createElement(name)
}
attributes.each { k, value ->
String valueText = (value != null) ? value.toString() : ""
element.setAttribute(k.toString(), valueText)
}
return element
}
protected void nodeCompleted(Object parent, Object node) {
if (namespaceAware) {
nsMap.pop()
}
}
protected QName parseQName(String name) {
String prefix = ''
String localPart = name
int i = name.indexOf(':')
if (i > -1) {
prefix = name.substring(0, i)
localPart = name.substring(i + 1)
}
String namespaceURI = nsMap.get(prefix)
return new QName(namespaceURI, localPart, prefix)
}
}
Update 3: here's an example of how to actually use it.
Element createGetSupplierPartyMaster(Dealer dealer, Customer customer = null)
{
assert dealer != null
assert dealer.dealerId != null
def builder = NSDOMBuilder.newInstance()
def el = builder.'ebiz:GetSupplierPartyMaster'(releaseID:'9.0',
xmlns:'http://www.openapplications.org/oagis/9',
'xmlns:ebiz':'http://www.dis-corp.com/xml/ebusiness/2.0') {
ApplicationArea() {
Sender(InetAddress.localHost.hostName)
CreationDateTime(dateTimeFormatter.print(new DateTime()))
BODID(UUID.randomUUID())
}
DataArea() {
Get() {
Expression()
}
SupplierPartyMaster() {
PartyIDs() {
ID(schemeURI:BODHelper.DEALER_SCHEME_URI, dealer.dealerId)
if (customer?.store)
{
ID(schemeURI:BODHelper.STORE_SCHEME_URI, customer.store.storeCode)
}
}
if (customer)
{
AccountIDs() {
ID(customer.customerNumber)
}
}
}
}
}
el.ownerDocument.appendChild(el)
return el
}
No comments:
Post a Comment