Search code examples
javaxmldomxml-parsingjoox

Filter XML Elements using JOOX then Write Full Document


Imagine an XML document like this:

<?xml version="1.0" encoding="UTF-8" ?>
<books>
  <book name="book1"></book>
  <book name="book2"></book>
</books>

I want to write the doc to a new file after filtering out some books. I'm using JOOX and have some code like this:

final FastFilter nameFilter = new FastFilter() {
    final Set<String> validNames = new HashSet<>();//contains "book1"
    @Override public boolean filter(Context context) {
        return !validNames.contains($(context).attr("name"));
    }
};      
final Document doc = $(new StringReader("entire text of xml document...")).document();
final Match m = $(doc).find("book").remove(nameFilter);

I tried something like this m.write(new File(output.xml));, but that outputs only:

<book name="book1"></book>

In other words it is missing the parent element <books> and also the initial XML declaration. Any idea how to accomplish this? Looking for a simple/elegant solution preferably using JOOX, not 20 lines of DOM code :)


Solution

  • You probably figured this out already, but in case you haven't:

    The Match m in your example represents the element* you wish to remove, in this case the book element with name="book1". When you call write() on a Match, it is only the element(s) of that Match which is written. Hence, when you do m.write(new File(output.xml)); you end up with

    <book name="book1"></book> 
    

    But the remove method removes the element(s) represented by the match (i.e. the book element with name "book1") from the Document you used to create/find the Match. So when you do remove(nameFilter), that element is actually removed from the Document doc.

    After the element is removed from the Document, if you want the entire edited Document written to file, you call the write method of (a Match of) the Document itself:

    $(doc).write(new File(output.xml)); 
    

    *) Do note that a Match can contain several elements. You can use m.size() to check the number of elements in your Match.