Is there any java xml library that can create xml tags with attributes in a defined order?
I have to create large xml files with 5 to 20 attributes per tag and I want the attributes ordered for better readability. Attributes which are always created should be at the beginning, followed by common attributes and rarely used attributes should be at the end.
Here's an easy way to create a custom outputter based on jdom:
JDOM uses XmlOutputter to convert a DOM into text output. Attributes are printed with the method:
protected void printAttributes(Writer out, List attributes, Element parent,
NamespaceStack namespaces) throws IOException
As you see, the attributes are passed with a simple list. The (simple) idea would be to subclass this outputter and override the method:
#Override
protected void printAttributes(Writer out, List attributes, Element parent,
NamespaceStack namespaces) throws IOException {
Collections.sort(attributes, new ByNameCompartor());
super.printAttributes(out, attribute, parent, namespaces);
}
The implementation of a comparator shouldn't be that difficult.
I'm not aware of any such library.
The problem is that the XML information model explicitly states that the order the attributes of a tag are irrelevant. Therefore, any in-memory XML representation that goes to the effort of preserving the ordering will more memory than is necessary and/or implement the attribute set/get methods suboptimally.
My advice would be to implement the ordering of attributes in the presentation of your XML content; e.g. in your XML editor.
I should point out that my Answer answers the Question as written - about "keeping the attributes in order". This could mean:
preserving the order of insertion, or
keeping in attributes sorted according to some ordering rule; e.g. ascending order.
From your comment below that you really just want to output the attributes in sorted order. This is a simpler problem, and can be addressed by customizing the code that serializes a DOM. Andreas_D explains how you can do this with JDOM, and there may be other options.
The other point is that something is a bit broken if the order of attributes in the input to a tool makes a significant difference to how it behaves. Because the order of XML attributes is supposed to be non-significant ...
Related
Probably, this is a duplicated question, but I cannot find the question I want to read, so I posted here.
I'm newbie of Antlr, and I try to use Antlr4 to make abstract syntax tree with visitor pattern in Scala.
However, I cannot come up with how to put together results of multiple rules like below into one list.
foo: (rule0 | rule1)*
rule0: ...
rule1: ...
I know there is a way to get each lists (i.e. list of rule0s and list of rule1s).
However, that way probably breaks the order of occurrence (I want to maintain the order).
The way like rules=(rule0 | rule1)* is not also allowed, so I cannot write like below
ctx.rules().asScala.map(...).toArray`
My question is how to put together into list of multiple rule results while maintaining order of appearance in visitor pattern.
The visitor is just a walker over the parse tree generated by your parse run. The visitor class iterates over the children of each parser context and calls the visitor functions. That means the actual information is stored in the parse tree and you can use it directly.
When you get a FooContext iterate over its children list, which contains the found Rule0Context and Rule1Context instances in the order they were used in the source code. This gives you both, the positional information about sub parts as well as the info about each of the sub parts.
Im trying to make a program which will build a tree from xml document via SAX parser.
But in result names of tags build sucsessful , but in attributes I see only attribute of last tag.
What is wrong with code?
Print to tree is in tag.toString()
Try to change line 48 into:
Tag t = new Tag(eName, new org.xml.sax.helpers.AttributesImpl(attrs));
I guess the problem is that you are storing the Attributes instance for each Tag, and that the Attributesinstance is reused for each each call to startElement() invokation. Thus, every Tag will will see the same attributes instance with the same content, that of the last one constructed by the parser. You will have to create a copy (or a Map or something else) of the actual attributes for each Tag.
I am trying to understand how to read out XML files using Java. I would like to have one XML tag, lets call it enable, pass a true to a method and another XML tag that provides a number to another method. I would like to pass the true by having the line in my XML file and pass the number as valueofnumber. I am reading out the XML file using a series of if statements testing for certain strings in an XML file:
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
if (localName.equals("enabled")){
currentConfig.setenabled(true);
}
else if (localName.equals("number")){
currentConfig.setnumber(Double.parseDouble(attributes.getValue("number")))
}
}
I am getting confused as to how extract the value of number from the XML file. Currently I am just getting an error that nothing is present when I try getIndex() as well.
Thanks very much in advance
The getValue() method you're calling takes a qualified name, meaning XML namespace + local name in the format :. Your XML document probably uses a namespace, which you'd have to supply. If there's no namespace, you might need to use the other getValue() method and pass null for the namespace. It all depends a lot on what parser you're using and how it's configured. You'd be better advised to move to a higher-level parsing library that takes care of these nuances for you:
StAX isn't much higher level than SAX, but it still has a friendlier and generally more intuitive interface.
JDOM, being a DOM parser, will be slightly less efficient, but it makes parsing XML incredibly easy.
Commons Digester is kind of a rules-based XML parsing engine. You establish rules for what you want to happen when this or that element or attribute is encountered, and then run the digester. Method calls are one of the rules you can set, as is creation and population of a POJO.
JAXB or XStream will completely remove the guesswork and bind the XML straight to POJOs with minimal configuration. Then you don't even have to deal with XML and can work with normal objects instead.
Edit: (Based on the XML sample) Your "number" isn't an attribute. It's a nested element. That's why you're having trouble getting it from the Attributes object. My other advice on other libraries still stands.
This question already has answers here:
Order of XML attributes after DOM processing
(12 answers)
Closed 9 years ago.
When writing in java the following:
Element fieldEl = targetDocument.createElement("field");
fieldEl.setAttribute("Wine","Marlo");
fieldEl.setAttribute("Beer","Corona");
The order of adding the attributes are not kept in the result XML file.
How can I control the order of the attribute inside XML Element (so it will be easy for human being to read...) ??
There is no defined order for attribute nodes according to the DOM standard:
Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes.
(emphasis added) and neither in the XML standard:
Note that the order of attribute specifications in a start-tag or empty-element tag is not significant.
I don't think, that many DOM implementations support ordering of attributes at all. You'd have to write your own serialization mechanism in order to achieve ordering (no pun intended).
The Facts
I have the following datastructure consisting of a table and a list of attributes (simplified):
class Table {
List<Attribute> m_attributes;
}
abstract class Attribute {}
class LongAttribute extends Attribute {}
class StringAttribute extends Attribute {}
class DateAttribute extends Attribute {}
...
Now I want to do different actions with this datastructure:
print it in XML notation
print it in textual form
create an SQL insert statement
create an SQL update statement
initialize it from a SQL result set
First Try
My first attempt was to put all these functionality inside the Attribute, but then the Attribute was overloaded with very different responsibilities.
Alternative
It feels like a visitor pattern could do the job very well instead, but on the other side it looks like overkill for this simple structure.
Question
What's the most elegant way to solve this?
I would look at using a combination of JAXB and Hibernate.
JAXB will let you marshall and unmarshall from XML. By default, properties are converted to elements with the same name as the property, but that can be controlled via #XmlElement and #XmlAttribute annotations.
Hibernate (or JPA) are the standard ways of moving data objects to and from a database.
The Command pattern comes to mind, or a small variation of it.
You have a bunch of classes, each of which is specialized to do a certain thing with your data class. You can keep these classes in a hashmap or some other structure where an external choice can pick one for execution. To do your thing, you call the selected Command's execute() method with your data as an argument.
Edit: Elaboration.
At the bottom level, you need to do something with each attribute of a data row.
This indeed sounds like a case for the Visitor pattern: Visitor simulates a double
dispatch operation, insofar as you are able to combine a variable "victim" object
with a variable "operation" encapsulated in a method.
Your attributes all want to be xml-ed, text-ed, insert-ed updat-ed and initializ-ed.
So you end up with a matrix of 5 x 3 classes to do each of these 5 operations
to each of 3 attribute types. The rest of the machinery of the visitor pattern
will traverse your list of attributes for you and apply the correct visitor for
the operation you chose in the right way for each attribute.
Writing 15 classes plus interface(s) does sound a little heavy. You can do this
and have a very general and flexible solution. On the other hand, in the time
you've spent thinking about a solution, you could have hacked together the code
to it for the currently known structure and crossed your fingers that the shape
of your classes won't change too much too often.
Where I thought of the command pattern was for choosing among a variety of similar
operations. If the operation to be performed came in as a String, perhaps in a
script or configuration file or such, you could then have a mapping from
"xml" -> XmlifierCommand
"text" -> TextPrinterCommand
"serial" -> SerializerCommand
...where each of those Commands would then fire up the appropriate Visitor to do
the job. But as the operation is more likely to be determined in code, you probably
don't need this.
I dunno why you'd store stuff in a database yourself these days instead of just using hibernate, but here's my call:
LongAttribute, DateAttribute, StringAttribute,… all have different internals (i.e. fields specific to them not present in Attribute class), so you cannot create one generic method to serialize them all. Now XML, SQL and plain text all have different properties when serializing to them. There's really no way you can avoid writing O(#subclasses of Attribute #output formats)* different methods of serializing.
Visitor is not a bad pattern for serializing. True, it's a bit overkill if used on non-recursive structures, but a random programmer reading your code will immediately grasp what it is doing.
Now for deserialization (from XML to object, from SQL to object) you need a Factory.
One more hint, for SQL update you probably want to have something that takes old version of the object, new version of the object and creates update query only on the difference between them.
In the end, I used the visitor pattern. Now looking back, it was a good choice.