1 package net.sf.saxon.event; 2 import net.sf.saxon.om.NamespaceConstant; 3 import net.sf.saxon.om.NamePool; 4 import net.sf.saxon.trans.XPathException; 5 import net.sf.saxon.type.Type; 6 import net.sf.saxon.value.Whitespace; 7 8 import javax.xml.transform.OutputKeys ; 9 import javax.xml.transform.Result ; 10 import java.util.ArrayList ; 11 import java.util.List ; 12 import java.util.Properties ; 13 14 20 21 public class UncommittedSerializer extends ProxyReceiver { 22 23 boolean committed = false; 24 List pending = null; 25 Result finalResult; 26 Properties outputProperties; 27 28 public UncommittedSerializer(Result finalResult, Properties outputProperties) { 29 this.finalResult = finalResult; 30 this.outputProperties = outputProperties; 31 setUnderlyingReceiver(new Sink()); 32 } 33 34 public void open() throws XPathException { 35 committed = false; 36 } 37 38 41 42 public void close() throws XPathException { 43 if (!committed) { 45 switchToMethod("xml"); 46 } 47 getUnderlyingReceiver().close(); 48 } 49 50 53 54 public void characters(CharSequence chars, int locationId, int properties) throws XPathException { 55 if (committed) { 56 getUnderlyingReceiver().characters(chars, locationId, properties); 57 } else { 58 if (pending==null) { 59 pending = new ArrayList (10); 60 } 61 PendingNode node = new PendingNode(); 62 node.kind = Type.TEXT; 63 node.name = null; 64 node.content = chars; 65 node.locationId = locationId; 66 node.properties = properties; 67 pending.add(node); 68 if (!Whitespace.isWhite(chars)) { 69 switchToMethod("xml"); 70 } 71 } 72 } 73 74 77 78 public void processingInstruction(String target, CharSequence data, int locationId, int properties) throws XPathException { 79 if (committed) { 80 getUnderlyingReceiver().processingInstruction(target, data, locationId, properties); 81 } else { 82 if (pending==null) { 83 pending = new ArrayList (10); 84 } 85 PendingNode node = new PendingNode(); 86 node.kind = Type.PROCESSING_INSTRUCTION; 87 node.name = target; 88 node.content = data; 89 node.locationId = locationId; 90 node.properties = properties; 91 pending.add(node); 92 } 93 } 94 95 98 99 public void comment (CharSequence chars, int locationId, int properties) throws XPathException { 100 if (committed) { 101 getUnderlyingReceiver().comment(chars, locationId, properties); 102 } else { 103 if (pending==null) { 104 pending=new ArrayList (10); 105 } 106 PendingNode node = new PendingNode(); 107 node.kind = Type.COMMENT; 108 node.name = null; 109 node.content = chars; 110 node.locationId = locationId; 111 node.properties = properties; 112 pending.add(node); 113 } 114 } 115 116 124 125 public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException { 126 if (!committed) { 127 NamePool namePool = getNamePool(); 128 String name = namePool.getLocalName(nameCode); 129 short uriCode = namePool.getURICode(nameCode); 130 if (name.equalsIgnoreCase("html") && uriCode==NamespaceConstant.NULL_CODE) { 131 switchToMethod("html"); 132 } else if (name.equals("html") && namePool.getURIFromURICode(uriCode).equals(NamespaceConstant.XHTML)) { 133 String version = outputProperties.getProperty(SaxonOutputKeys.STYLESHEET_VERSION); 134 if ("1".equals(version)) { 135 switchToMethod("xml"); 136 } else { 137 switchToMethod("xhtml"); 138 } 139 } else { 140 switchToMethod("xml"); 141 } 142 } 143 getUnderlyingReceiver().startElement(nameCode, typeCode, locationId, properties); 144 } 145 146 149 150 private void switchToMethod(String method) throws XPathException { 151 Properties newProperties = new Properties (outputProperties); 152 newProperties.setProperty(OutputKeys.METHOD, method); 153 Receiver target = ResultWrapper.getReceiver(finalResult, getPipelineConfiguration(), newProperties); 154 committed = true; 155 target.open(); 156 target.startDocument(0); 157 if (pending!=null) { 158 for (int i = 0; i < pending.size(); i++) { 159 PendingNode node = (PendingNode)pending.get(i); 160 switch (node.kind) { 161 case Type.COMMENT: 162 target.comment(node.content, node.locationId, node.properties); 163 break; 164 case Type.PROCESSING_INSTRUCTION: 165 target.processingInstruction(node.name, node.content, node.locationId, node.properties); 166 break; 167 case Type.TEXT: 168 target.characters(node.content, node.locationId, node.properties); 169 break; 170 } 171 } 172 pending = null; 173 } 174 setUnderlyingReceiver(target); 175 } 176 177 181 182 private static final class PendingNode { 183 int kind; 184 String name; 185 CharSequence content; 186 int properties; 187 int locationId; 188 } 189 190 } 191 192 | Popular Tags |