jayzee
jayzee

Reputation: 225

Parse XML using SAX and get only one element based on value

Hello I'm trying to parse an xml file using SAX and filter it based on an element value and save the result in another file.

the XML file example:

<ruleset>
    <rule>
        <condition>
            <case1>String testing</case1>
            <allow>true</allow>
        </condition>
    </rule>
    <rule>
        <condition>
            <case2>String test</case2>
            <allow>false</allow>
        </condition>
    </rule>
</ruleset>

I want the result file to be as follows

<ruleset>
    <rule>
        <condition>
            <case2>String test</case2>
            <allow>false</allow>
        </condition>
    </rule>
</ruleset>

Since the tag has the value "false", So mainly I want to filter the loop element based on the element's value

The code till now helps me filter the all the elements based on the parent element but not on the element.

final String splitElement = "Rule";


        XMLReader xr = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) {

            private boolean skip;

            public void startElement(String uri, String localName, String qName, org.xml.sax.Attributes atts)
                    throws SAXException {

                if (qName.equals(splitElement)) {

                    super.startElement(uri, localName, qName, atts);
                    skip = false;
                    
                } else {
                    if (!skip) {
                        super.startElement(uri, localName, qName, atts);
                    }
                }
            }
            
            
            public void endElement(String uri, String localName, String qName) throws SAXException {
                if (!skip) {
                    super.endElement(uri, localName, qName);
                }
            }

            public void characters(char[] ch, int start, int length) throws SAXException {
                if (!skip) {
                    super.characters(ch, start, length);
                }
            }

        };

        Source src = new SAXSource(xr, new InputSource(
                "SourceFilePath"));
        StreamResult res = new StreamResult(new File(
                "DestinantionFilePath"));
        TransformerFactory.newInstance().newTransformer().transform(src, res);

Is it possible to do that using a SAX parser and only keep the "rules" that have an as false ?

Upvotes: 0

Views: 400

Answers (1)

Michael Kay
Michael Kay

Reputation: 163302

Not easy because it requires lookahead - you can't decide what do with a rule start tag until you see the allow value some time later. The easiest way would be start building a DOM(or DOM-like) tree for each rule, and when you hit the rule end tag, decide whether to keep it or discard it.

If you want a streaming solution to this problem using XSLT 3.0, it's

<xsl:mode streamable="yes" on-no-match="shallow-copy"/>
<xsl:template match="rule">
  <xsl:sequence select="copy-of(.)[condition/allow='true']"/>
</xsl:template>

Upvotes: 1

Related Questions