Dazed
Dazed

Reputation: 1259

How to create a new xml file with Joox

I'm trying to create a new xml with a structure and at the same time add elements via this

String styleName = "myStyle";
String styleKey = "styleKeyValue";

File file = new File("test.xml");        

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document document = builder.newDocument();

Match x = $(document)
                .namespace("s", "http://www.mycompany.com/data")
                .append(
                    $("Data",
                        $("Styles",
                            $("Style",
                                $("Attributes", "")
                            ).attr("name", styleName)
                        )
                    )
                );

Match xpath = x.xpath("//s:Attributes");

xpath = xpath.append($("Attribute", "").attr("key", styleKey));

x.write(file);

However .append doesn't seem to add anything and I end up with an empty file.
This approach is based on this SO answer but the "Document document = $(file).document();" line gives me an exception as the file doesn't exist - hence the use of DocumentBuilder.

Of course I realise that I can create new xml file through a host of other means I am trying to stick with Joox based approach at the moment.

Upvotes: 2

Views: 1029

Answers (2)

Dazed
Dazed

Reputation: 1259

Working version after feedback from Lucas Eder (Joox "all the way" option)

// Initial block to create xml structure
Match x = $("Data",
             $("Styles",
                $("Style",
                    $("Attributes", "")                                            
                 ).attr("name", styleName)
              )
           ).attr("xmlns", "http://www.mycompany.com/data");

// example xpath into structure to add element attribues
// as required
Match xpath = x.xpath("//Attributes");

xpath = xpath.append($("Attribute", "").attr("key", styleKey));

x.write(file);

Produces the following:

<Data xmlns="http://www.mycompany.com/data">
    <Styles>
        <Style name="myStyle">
            <Attributes>
                <Attribute key="styleKeyValue"/>
            </Attributes>
        </Style>
    </Styles>
</Data>

Upvotes: 3

Lukas Eder
Lukas Eder

Reputation: 220842

The problem here is a misunderstanding of what Match.append() does. Let's look at it this way

The Javadoc reads:

Append content to the end of each element's content in the set of matched elements.

Now, if you do this:

Match x = $(document);

This just wraps an existing document in a jOOX Match wrapper for further processing. This Match wrapper matches no elements at all, because there are no elements in the wrapped document, not even a root element (you created a new one). So, in order to actually create a document with elements, you have to:

  • Either create the root element using the DOM API
  • Or use jOOX all the way, as can be seen below:

    Match x = $("Data",
                $("Styles",
                  $("Style",
                    $("Attributes", "")
                   ).attr("name", styleName)
                 )
               );
    

Note that your Match.namespace() call does not have the effect you'd like it to have. There is currently no way to set a namespace on jOOX-generated elements. This is the pending feature request for this feature: https://github.com/jOOQ/jOOX/issues/133

The Match.namespace() method simply binds a namespace to a prefix in the match context, for subsequent xpath() calls. Here's the Javadoc extract of the method:

Get a new Match with added namespace configuration for subsequent XPath calls

Upvotes: 1

Related Questions