Added single-tag vs dual-tag distinction to strict parser
This commit is contained in:
parent
270f4314d6
commit
45b26c5f7e
1 changed files with 124 additions and 0 deletions
|
@ -0,0 +1,124 @@
|
|||
package net.vhati.modmanager.core;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.jdom2.Element;
|
||||
import org.jdom2.JDOMFactory;
|
||||
import org.jdom2.Parent;
|
||||
import org.jdom2.Text;
|
||||
import org.jdom2.input.sax.SAXHandler;
|
||||
import org.jdom2.input.sax.SAXHandlerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* A factory that produces SAXHandlers which distinguish tag-pairs from dual tags.
|
||||
*
|
||||
* While this factory is registered with a SAXBuilder, strict parsing
|
||||
* will occur as normal, notifying the SAXHandler of progress. When
|
||||
* the handler hears that a tag ended at a different line/column than
|
||||
* where it started, and no other text was reported along the way, a
|
||||
* zero-length text node will be added as token content.
|
||||
*
|
||||
* Later, when the Element tree is printed, a special
|
||||
* XMLOutputProcessor can reproduce the tag pair pased on the
|
||||
* presence of child Content objects - like the dummy string - rather
|
||||
* than the presence of non-whitespace text after formatting.
|
||||
*
|
||||
* Note: Not all XMLReaders offer a Locator for line/col info. When
|
||||
* that info is not available, this handler will do nothing special.
|
||||
*
|
||||
* @see org.jdom2.input.SAXBuilder#setSAXHandlerFactory(SAXHandlerFactory factory)
|
||||
*/
|
||||
public class EmptyAwareSAXHandlerFactory implements SAXHandlerFactory {
|
||||
|
||||
@Override
|
||||
public SAXHandler createSAXHandler( JDOMFactory factory ) {
|
||||
return new EmptyAwareSAXHandler( factory );
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class EmptyAwareSAXHandler extends SAXHandler {
|
||||
|
||||
boolean emptyTag = true;
|
||||
int startTagLine = -1;
|
||||
int startTagColumn = -1;
|
||||
|
||||
public EmptyAwareSAXHandler( JDOMFactory factory ) {
|
||||
super( factory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement( String namespaceURI, String localName, String qName, Attributes atts ) throws SAXException {
|
||||
emptyTag = true;
|
||||
startTagLine = -1;
|
||||
startTagColumn = -1;
|
||||
|
||||
Locator loc = getDocumentLocator();
|
||||
if ( loc != null ) {
|
||||
startTagLine = loc.getLineNumber();
|
||||
startTagColumn = loc.getColumnNumber();
|
||||
}
|
||||
super.startElement( namespaceURI, localName, qName, atts );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void comment( char[] ch, final int start, final int length ) throws SAXException {
|
||||
emptyTag = false;
|
||||
super.comment( ch, start, length );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters( char[] ch, final int start, final int length ) throws SAXException {
|
||||
emptyTag = false;
|
||||
super.characters( ch, start, length );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ignorableWhitespace( char[] ch, int start, int length) throws SAXException {
|
||||
emptyTag = false;
|
||||
super.characters( ch, start, length );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processingInstruction( String target, String data ) throws SAXException {
|
||||
super.processingInstruction( target, data );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startCDATA() {
|
||||
emptyTag = false;
|
||||
super.startCDATA();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement( String namespaceURI, String localName, String qName ) throws SAXException {
|
||||
Element closedElement = getCurrentElement();
|
||||
boolean twoPartTag = false;
|
||||
|
||||
Locator loc = getDocumentLocator();
|
||||
if ( loc != null ) {
|
||||
int endTagLine = loc.getLineNumber();
|
||||
int endTagColumn = loc.getColumnNumber();
|
||||
|
||||
if ( startTagLine != -1 && endTagLine != -1 && startTagLine != endTagLine) {
|
||||
twoPartTag = true;
|
||||
}
|
||||
else if ( startTagColumn != -1 && endTagColumn != -1 && startTagColumn != endTagColumn ) {
|
||||
twoPartTag = true;
|
||||
}
|
||||
}
|
||||
|
||||
super.endElement( namespaceURI, localName, qName );
|
||||
|
||||
if ( emptyTag && twoPartTag && closedElement.getContent().isEmpty() ) {
|
||||
// This is a separate closing tag after an empty value.
|
||||
// Add a blank text node.
|
||||
|
||||
final Text text = getFactory().text( "" );
|
||||
getFactory().addContent( closedElement, text );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue