2.3.3. fejezet, Szerver válasz kódolási receptek

A szerver kimenetét megfelelően kódolni kell. Az UTF-8 karakter kódolás jó választás, mivel mindkét böngésző támogatja, és nemzetközi tartalomgenerálásra általánosan használható.

	private void transferToOutput(Document content, HttpServletResponse response) throws IOException {
		ServletOutputStream out = response.getOutputStream();
		if (content != null) {
			response.setCharacterEncoding("utf-8");
			response.setContentType("text/xml");
			config.getResourceContainer().writeLog("Begining of XML result transfer.", Level.INFO);
			if (generateDebugInfo) {
				ByteArrayOutputStream ostream = new ByteArrayOutputStream();
				OutputStreamWriter sout = new OutputStreamWriter(ostream, "utf-8");
				XMLTk.transfer(content, sout);
				content = null;
				ostream.writeTo(out);
				config.getResourceContainer().writeLog(ostream, Level.INFO);
			} else {
				OutputStreamWriter sout = new OutputStreamWriter(out, "utf-8");
				XMLTk.transfer(content, sout);
				sout.flush();
				content = null;
			}
			out.flush();
			config.getResourceContainer().writeLog("End of XML result transfer.", Level.INFO);
		}
		out.close();
	}

Multipart módon küldve többféle tartalom egybe fűzhető, habár az IE6 ezt a módszert nem támogatja.

	public void transferToOutputMultipart(Document content, HttpServletResponse response) throws IOException {
		// multipart result generator (jquery.forms not supported)
		String BOUNDARY_STR = getBoundaryStr();
		String BOUNDARY_START = "--" + BOUNDARY_STR;
		String BOUNDARY_END = BOUNDARY_START + "--";
		response.setContentType("multipart/x-mixed-replace;boundary=\"" + BOUNDARY_STR + "\"");
		ServletOutputStream out = response.getOutputStream();
		int partCount = 0;
		if (content != null) {//While cycle for each part
			out.println(BOUNDARY_START);
			response.setCharacterEncoding("utf-8");
			out.println("Content-type: text/xml;charset=utf-8\n");
			config.getResourceContainer().writeLog("Begining of Multipart "+partCount+". part XML result transfer.", Level.INFO);
			if (generateDebugInfo) {
				ByteArrayOutputStream ostream = new ByteArrayOutputStream();
				OutputStreamWriter sout = new OutputStreamWriter(ostream, "utf-8");
				XMLTk.transfer(content, sout);
				content = null;
				ostream.writeTo(out);
				config.getResourceContainer().writeLog(ostream, Level.INFO);
			} else {
				OutputStreamWriter sout = new OutputStreamWriter(out, "utf-8");
				XMLTk.transfer(content, sout);
				content = null;
				sout.flush();
			}
			out.flush();
			config.getResourceContainer().writeLog("End of Multipart "+partCount+". part XML result transfer.", Level.INFO);
			partCount++;
		}
		// serviceCall.getMediaResultIterator();
		if (partCount > 0) {
			out.println(BOUNDARY_END);
			out.flush();
		}
		out.close();
	}

Az elválasztó karaktereket MD5 algoritmussal előállítva elkerülhető a küldött tartalomba véletlenül bekerülő elválasztó karakterek multipart rész lezáróként történő félreértése.

	public static String getMD5Sum(byte[] value) throws NoSuchAlgorithmException{
		MessageDigest algorithm = MessageDigest.getInstance("MD5");
		algorithm.reset();
		algorithm.update(value);
		byte messageDigest[] = algorithm.digest();
 
		StringBuffer hexString = new StringBuffer();
		for (int i = 0; i < messageDigest.length; i++) {
			hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
		}
		return hexString.toString();
	}

Érdemes a value értékébe az aktuális dátumot betenni.

	private String getBoundaryStr() {
                Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("Europa/Budapest"));
		String BOUNDARY_STR = null;
		long time = calendar.getTimeInMillis();
		byte[] defaultBytes = Long.toHexString(time).getBytes();
		try {
			BOUNDARY_STR = StrTk.getMD5Sum(defaultBytes);
		} catch (NoSuchAlgorithmException e) {
			BOUNDARY_STR = "0x34243285923167467324";
		}
		return BOUNDARY_STR;
	}

UTF-8 XML dokumentum kiírása az OutputStream-re nem is olyan egyszerű. Fontos használni a PI_DISABLE_OUTPUT_ESCAPING feldolgozási utasítást, mivel máskülönben az adatbázisban tárolt speciális karakterek, mint például az & átalakul &amp; formába, ami rossz eredményre vezethet a html tartalom előállításánál. Ez esetben korábban a szerkesztőmezőbe beírt &amp; tartalmat újabb szerkesztéskor &amp;amp;-ként láthatjuk viszont, és ez persze nem egyezik meg az előzőleg elmentett értékkel.

	public static void transfer(Document content, OutputStreamWriter out) {
		try {
			Node root = content.getFirstChild();
			if (root != null) {
				ProcessingInstruction pi = content.createProcessingInstruction(Result.PI_DISABLE_OUTPUT_ESCAPING, "");
				root.getParentNode().insertBefore(pi, root);
			}
			Transformer serializer = TransformerFactory.newInstance().newTransformer();
			serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
			serializer.setOutputProperty(OutputKeys.INDENT, "yes");
			serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
			serializer.setOutputProperty(OutputKeys.METHOD, "xml");
			DOMSource source = new DOMSource(content);
			StreamResult result = new StreamResult(out);
			serializer.transform(source, result);
		} catch (TransformerConfigurationException ex) {
 
		} catch (TransformerException ex) {
 
		}

StringBuffer tartalom összeállításánál érdemes HTML enkódolást alkalmazi az adatbázisból származó speciális karakterek átalakítására. Így elkerülhető a tartalom összeférhetetlensége az XML tagokkal.

	public static boolean isXMLCompliant(char c) {
		int type = Character.getType(c);
		boolean result = Character.isLetterOrDigit(c) || Character.isWhitespace(c) || type == Character.DASH_PUNCTUATION
                        || type == Character.START_PUNCTUATION || type == Character.END_PUNCTUATION 
                        || type == Character.CONNECTOR_PUNCTUATION
		        || type == Character.MATH_SYMBOL || type == Character.OTHER_PUNCTUATION;
		return result && (c != '&') && (c != '<');
	}
 
	public static String HTMLEnc(String s) {
		StringBuffer buff = new StringBuffer();
		int len = (s == null ? -1 : s.length());
		for (int i = 0; i < len; i++) {
			char c = s.charAt(i);
			if (isXMLCompliant(c))
				buff.append(c);
			else
				buff.append("&#" + (int) c + ";");
		}
		return buff.toString();