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