DCH
DCH

Reputation: 309

Modify XML File with SAX

I'm currently trying to generate a set of models (specified via XML). In order to achieve this, I need to change a single attribute inside the file and save it under a new file name.

The XML File looks like this:

(...)
<place id="P19" initialMarking="0" invariant="&lt; inf" markingOffsetX="0.0" markingOffsetY="0.0" name="P19" nameOffsetX="-5.0" nameOffsetY="35.0" positionX="615.0" positionY="375.0"/>
<place id="P20" initialMarking="0" invariant="&lt; inf" markingOffsetX="0.0" markingOffsetY="0.0" name="P20" nameOffsetX="-5.0" nameOffsetY="35.0" positionX="375.0" positionY="225.0"/>
(...)

What needs changing is the value of initialMarking to values from 2 through 999.

Here is what I have so far: This is where I get the list of files to change and pass them to the parser

public void parse(String dir){
        getFiles(dir);

        try {
            XMLReader xmlReader = XMLReaderFactory.createXMLReader();

            for(int i = 0; i < fileList.length; i++) {
                FileReader reader = new FileReader(fileList[i]);
                InputSource inputSource = new InputSource(reader);
                xmlReader.setContentHandler(new ModelContentHandler());
                xmlReader.parse(inputSource);
            }
(...)

This is where I'm searching for the element I need to change:

public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        if(localName.equals("place") && atts.getValue(0).equals("P14") && atts.getValue(1).equals("2")){
            System.out.println("Initial Marking of " + atts.getValue(0) + " is: " + atts.getValue(1) + "\n");
            while(currentTokens <= Configuration.MAX_TOKENS){
                System.out.println("Setting initial Tokens to: " + currentTokens);

            }
        }
    }

Now, instead of printing out "Setting..." I'd like to change the according value and just save the whole file under some new name like "Model_X_Y_Token.xml".

Seems like a fairly simple thing to do, but I've never used SAX before and looking at the JavaDoc, I can't even find a place to start. Maybe someone can point me in the right direction?

Upvotes: 1

Views: 2711

Answers (2)

vtd-xml-author
vtd-xml-author

Reputation: 3377

The most efficient way possible is with vtd-xml as it is the only API that does something called incremental update...

import com.ximpleware.*;

public class changeAttrVal {
    public  static  void main(String s[]) throws VTDException,java.io.UnsupportedEncodingException,java.io.IOException{
        VTDGen vg = new VTDGen();
        if (!vg.parseFile("input.xml", false))
            return;
        VTDNav vn = vg.getNav();
        AutoPilot ap = new AutoPilot(vn);
        XMLModifier xm = new XMLModifier(vn);
        ap.selectXPath("/*/place[@id=\"p14\" and   @initialMarking=\"2\"]/@initialMarking");
        int i=0;
        while((i=ap.evalXPath())!=-1){
            xm.updateToken(i+1, "499");// change initial marking from 2 to 499
        }
        xm.output("new.xml"); // output to a new document called new.xml
    }

}

Upvotes: 0

YashGhatti
YashGhatti

Reputation: 26

One of the best approaches here is to use dom4j.I don't exactly get the big picture of what you're trying to do, but I understand the result you want to get. Note that you will also need jaxen for this.

Step 1 : read the file into an xml doxument

for(int i=0; i<fileList.length; i++){
        Document doc = new SAXReader().read(fileList[i]);
    }

Step 2 : parse the elements you need. For this you need to know a bit of xpath. ///place will fetch all the place elements. ///place[@id="P14"] will fetch only one place element.

Element place14 = (Element) doc.selectSingleNode("//*/place[@id="p14" and   initialMarking="2"]");

Step 3 : change the attributes of the element

plac14.attribute("attributename").setValue("attributeValue");

Upvotes: 1

Related Questions