Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/188.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ksoap2 android:需要将原始XML作为值,而不转义特殊字符_Android_Xml_Android Ksoap2 - Fatal编程技术网

ksoap2 android:需要将原始XML作为值,而不转义特殊字符

ksoap2 android:需要将原始XML作为值,而不转义特殊字符,android,xml,android-ksoap2,Android,Xml,Android Ksoap2,我正在使用ksoap2来使用SOAP WS。我唯一需要从库中得到的是验证信封并与WS通信,“body”xml是从其他地方使用简单xml的对象生成的 因此,我需要的是将xml(已作为字符串传递)作为值,但ksoap2使用>和<来转义我的xml标记 我在这里搜索过,我发现最相似的问题是哪一点哪一点。无论如何,我不想再次马歇尔一个对象,我的结构相当大,它还包括一个签名,我已经用另一个库解决了所有这些问题 所以,实际的问题是:在ksoap2android中有没有办法避免以字符串形式转义xml?我

我正在使用ksoap2来使用SOAP WS。我唯一需要从库中得到的是验证信封并与WS通信,“body”xml是从其他地方使用简单xml的对象生成的

因此,我需要的是将xml(已作为字符串传递)作为值,但ksoap2使用>和<来转义我的xml标记

我在这里搜索过,我发现最相似的问题是哪一点哪一点。无论如何,我不想再次马歇尔一个对象,我的结构相当大,它还包括一个签名,我已经用另一个库解决了所有这些问题


所以,实际的问题是:在ksoap2android中有没有办法避免以字符串形式转义xml?

我已经回顾了在soap请求的“body”标记中发送“fhateva”。也就是说,我考虑在正文中发送我们作为字符串提供的xml。 做这样的事情通常不是个好主意,但——有时这确实是做一些丑陋但资源高效的事情的最佳方式——fe。您的xml字符串解析、更改为可序列化和序列化似乎也不是很好

下面我介绍了三个类,它们是对SoapSerializationEnvelope、HttpTransportSE和KXmlSerializer的修改。其中两个只需要小的更改,可以通过继承类添加。但是需要包含在ksoap2-android-assembly-3.4.0-jar-with-dependencies中的类HttpTransportSE,因为方法“getPrefixes”。修改其他传输类取决于您:P

不幸的是,KXmlSerializer隐藏了所有不是XmlSerializer的东西,所以-这里有一个经过修改的完整类 这与您使用Android编程的类相同或几乎相同

我警告每个人,必须使用“那个东西”——它是真正的恐怖主义,并且试着只在维护成本方面使用它,这将由你或你的同事承担。第二个方面——KXmlSerializer相对来说比较旧,不经常更改

使用“那个东西”的示例:

TerroSerializationEnvelope=新的TerroserizationEnvelope(SoapEnvelope.VER11);
envelope.dotNet=true;
envelope.setOutputSoapObject(请求);
String src=“string1string1string1gstring1strings1tringstring1gst1ringba1se64binary”;
信封.setOutputString(src);
TerroHttpTransportSE androidHttpTransport=新的TerroHttpTransportSE(URL);
尝试
{
androidHttpTransport.debug=true;
调用(SOAP_操作,信封);
SoapObject响应=(SoapObject)信封.getResponse();
}
捕获(例外e)
{   ...
和修改类:

/** 
 * Copyright (c) 2006, James Seigel, Calgary, AB., Canada
 * Copyright (c) 2003,2004, Stefan Haustein, Oberhausen, Rhld., Germany
 * 
 * For full licences see links that are included in post above
**/
class TerroKXmlSerializer implements XmlSerializer {

    //    static final String UNDEFINED = ":";

    // BEGIN android-added
    /** size (in characters) for the write buffer */
    private static final int WRITE_BUFFER_SIZE = 500;
    // END android-added

    // BEGIN android-changed
    // (Guarantee that the writer is always buffered.)
    private BufferedWriter writer;
    // END android-changed

    private boolean pending;
    private int auto;
    private int depth;

    private String[] elementStack = new String[12];
    //nsp/prefix/name
    private int[] nspCounts = new int[4];
    private String[] nspStack = new String[8];
    //prefix/nsp; both empty are ""
    private boolean[] indent = new boolean[4];
    private boolean unicode;
    private String encoding;

    private final void check(boolean close) throws IOException {
        if (!pending)
            return;

        depth++;
        pending = false;

        if (indent.length <= depth) {
            boolean[] hlp = new boolean[depth + 4];
            System.arraycopy(indent, 0, hlp, 0, depth);
            indent = hlp;
        }
        indent[depth] = indent[depth - 1];

        for (int i = nspCounts[depth - 1]; i < nspCounts[depth]; i++) {
            writer.write(' ');
            writer.write("xmlns");
            if (!nspStack[i * 2].isEmpty()) {
                writer.write(':');
                writer.write(nspStack[i * 2]);
            }
            else if (getNamespace().isEmpty() && !nspStack[i * 2 + 1].isEmpty())
                throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
            writer.write("=\"");
            writeEscaped(nspStack[i * 2 + 1], '"');
            writer.write('"');
        }

        if (nspCounts.length <= depth + 1) {
            int[] hlp = new int[depth + 8];
            System.arraycopy(nspCounts, 0, hlp, 0, depth + 1);
            nspCounts = hlp;
        }

        nspCounts[depth + 1] = nspCounts[depth];
        //   nspCounts[depth + 2] = nspCounts[depth];

        writer.write(close ? " />" : ">");
    }

    private final void writeEscaped(String s, int quot) throws IOException {
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
                case '\n':
                case '\r':
                case '\t':
                    if(quot == -1)
                        writer.write(c);
                    else
                        writer.write("&#"+((int) c)+';');
                    break;
                case '&' :
                    writer.write("&amp;");
                    break;
                case '>' :
                    writer.write("&gt;");
                    break;
                case '<' :
                    writer.write("&lt;");
                    break;
                default:
                    if (c == quot) {
                        writer.write(c == '"' ? "&quot;" : "&apos;");
                        break;
                    }
                    // BEGIN android-changed: refuse to output invalid characters
                    // See http://www.w3.org/TR/REC-xml/#charsets for definition.
                    // No other Java XML writer we know of does this, but no Java
                    // XML reader we know of is able to parse the bad output we'd
                    // otherwise generate.
                    // Note: tab, newline, and carriage return have already been
                    // handled above.
                    boolean valid = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
                    if (!valid) {
                        reportInvalidCharacter(c);
                    }
                    if (unicode || c < 127) {
                        writer.write(c);
                    } else {
                        writer.write("&#" + ((int) c) + ";");
                    }
                    // END android-changed
            }
        }
    }

    // BEGIN android-added
    private static void reportInvalidCharacter(char ch) {
        throw new IllegalArgumentException("Illegal character (" + Integer.toHexString((int) ch) + ")");
    }
    // END android-added

    /*
        private final void writeIndent() throws IOException {
            writer.write("\r\n");
            for (int i = 0; i < depth; i++)
                writer.write(' ');
        }*/

    public void docdecl(String dd) throws IOException {
        writer.write("<!DOCTYPE");
        writer.write(dd);
        writer.write(">");
    }

    public void endDocument() throws IOException {
        while (depth > 0) {
            endTag(elementStack[depth * 3 - 3], elementStack[depth * 3 - 1]);
        }
        flush();
    }

    public void entityRef(String name) throws IOException {
        check(false);
        writer.write('&');
        writer.write(name);
        writer.write(';');
    }

    public boolean getFeature(String name) {
        //return false;
        return (
            "http://xmlpull.org/v1/doc/features.html#indent-output"
                .equals(
                name))
            ? indent[depth]
            : false;
    }

    public String getPrefix(String namespace, boolean create) {
        try {
            return getPrefix(namespace, false, create);
        }
        catch (IOException e) {
            throw new RuntimeException(e.toString());
        }
    }

    private final String getPrefix(
        String namespace,
        boolean includeDefault,
        boolean create)
        throws IOException {

        for (int i = nspCounts[depth + 1] * 2 - 2;
            i >= 0;
            i -= 2) {
            if (nspStack[i + 1].equals(namespace)
                && (includeDefault || !nspStack[i].isEmpty())) {
                String cand = nspStack[i];
                for (int j = i + 2;
                    j < nspCounts[depth + 1] * 2;
                    j++) {
                    if (nspStack[j].equals(cand)) {
                        cand = null;
                        break;
                    }
                }
                if (cand != null)
                    return cand;
            }
        }

        if (!create)
            return null;

        String prefix;

        if (namespace.isEmpty())
            prefix = "";
        else {
            do {
                prefix = "n" + (auto++);
                for (int i = nspCounts[depth + 1] * 2 - 2;
                    i >= 0;
                    i -= 2) {
                    if (prefix.equals(nspStack[i])) {
                        prefix = null;
                        break;
                    }
                }
            }
            while (prefix == null);
        }

        boolean p = pending;
        pending = false;
        setPrefix(prefix, namespace);
        pending = p;
        return prefix;
    }

    public Object getProperty(String name) {
        throw new RuntimeException("Unsupported property");
    }

    public void ignorableWhitespace(String s)
        throws IOException {
        text(s);
    }

    public void setFeature(String name, boolean value) {
        if ("http://xmlpull.org/v1/doc/features.html#indent-output"
            .equals(name)) {
            indent[depth] = value;
        }
        else
            throw new RuntimeException("Unsupported Feature");
    }

    public void setProperty(String name, Object value) {
        throw new RuntimeException(
            "Unsupported Property:" + value);
    }

    public void setPrefix(String prefix, String namespace)
        throws IOException {

        check(false);
        if (prefix == null)
            prefix = "";
        if (namespace == null)
            namespace = "";

        String defined = getPrefix(namespace, true, false);

        // boil out if already defined

        if (prefix.equals(defined))
            return;

        int pos = (nspCounts[depth + 1]++) << 1;

        if (nspStack.length < pos + 1) {
            String[] hlp = new String[nspStack.length + 16];
            System.arraycopy(nspStack, 0, hlp, 0, pos);
            nspStack = hlp;
        }

        nspStack[pos++] = prefix;
        nspStack[pos] = namespace;
    }

    public void setOutput(Writer writer) {
        // BEGIN android-changed
        // Guarantee that the writer is always buffered.
        if (writer instanceof BufferedWriter) {
            this.writer = (BufferedWriter) writer;
        } else {
            this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE);
        }
        // END android-changed

        // elementStack = new String[12]; //nsp/prefix/name
        //nspCounts = new int[4];
        //nspStack = new String[8]; //prefix/nsp
        //indent = new boolean[4];

        nspCounts[0] = 2;
        nspCounts[1] = 2;
        nspStack[0] = "";
        nspStack[1] = "";
        nspStack[2] = "xml";
        nspStack[3] = "http://www.w3.org/XML/1998/namespace";
        pending = false;
        auto = 0;
        depth = 0;

        unicode = false;
    }

    public void setOutput(OutputStream os, String encoding)
        throws IOException {
        if (os == null)
            throw new IllegalArgumentException("os == null");
        setOutput(
            encoding == null
                ? new OutputStreamWriter(os)
                : new OutputStreamWriter(os, encoding));
        this.encoding = encoding;
        if (encoding != null && encoding.toLowerCase(Locale.US).startsWith("utf")) {
            unicode = true;
        }
    }

    public void startDocument(String encoding, Boolean standalone) throws IOException {
        writer.write("<?xml version='1.0' ");

        if (encoding != null) {
            this.encoding = encoding;
            if (encoding.toLowerCase(Locale.US).startsWith("utf")) {
                unicode = true;
            }
        }

        if (this.encoding != null) {
            writer.write("encoding='");
            writer.write(this.encoding);
            writer.write("' ");
        }

        if (standalone != null) {
            writer.write("standalone='");
            writer.write(
                standalone.booleanValue() ? "yes" : "no");
            writer.write("' ");
        }
        writer.write("?>");
    }

    public XmlSerializer startTag(String namespace, String name)
        throws IOException {
        check(false);

        //        if (namespace == null)
        //            namespace = "";

        if (indent[depth]) {
            writer.write("\r\n");
            for (int i = 0; i < depth; i++)
                writer.write("  ");
        }

        int esp = depth * 3;

        if (elementStack.length < esp + 3) {
            String[] hlp = new String[elementStack.length + 12];
            System.arraycopy(elementStack, 0, hlp, 0, esp);
            elementStack = hlp;
        }

        String prefix =
            namespace == null
                ? ""
                : getPrefix(namespace, true, true);

        if (namespace != null && namespace.isEmpty()) {
            for (int i = nspCounts[depth];
                i < nspCounts[depth + 1];
                i++) {
                if (nspStack[i * 2].isEmpty() && !nspStack[i * 2 + 1].isEmpty()) {
                    throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
                }
            }
        }

        elementStack[esp++] = namespace;
        elementStack[esp++] = prefix;
        elementStack[esp] = name;

        writer.write('<');
        if (!prefix.isEmpty()) {
            writer.write(prefix);
            writer.write(':');
        }

        writer.write(name);

        pending = true;

        return this;
    }

    public XmlSerializer attribute(
        String namespace,
        String name,
        String value)
        throws IOException {
        if (!pending)
            throw new IllegalStateException("illegal position for attribute");

        //        int cnt = nspCounts[depth];

        if (namespace == null)
            namespace = "";

        //        depth--;
        //        pending = false;

        String prefix =
            namespace.isEmpty()
                ? ""
                : getPrefix(namespace, false, true);

        //        pending = true;
        //        depth++;

        /*        if (cnt != nspCounts[depth]) {
                    writer.write(' ');
                    writer.write("xmlns");
                    if (nspStack[cnt * 2] != null) {
                        writer.write(':');
                        writer.write(nspStack[cnt * 2]);
                    }
                    writer.write("=\"");
                    writeEscaped(nspStack[cnt * 2 + 1], '"');
                    writer.write('"');
                }
                */

        writer.write(' ');
        if (!prefix.isEmpty()) {
            writer.write(prefix);
            writer.write(':');
        }
        writer.write(name);
        writer.write('=');
        char q = value.indexOf('"') == -1 ? '"' : '\'';
        writer.write(q);
        writeEscaped(value, q);
        writer.write(q);

        return this;
    }

    public void flush() throws IOException {
        check(false);
        writer.flush();
    }
    /*
        public void close() throws IOException {
            check();
            writer.close();
        }
    */
    public XmlSerializer endTag(String namespace, String name)
        throws IOException {

        if (!pending)
            depth--;
        //        if (namespace == null)
        //          namespace = "";

        if ((namespace == null
            && elementStack[depth * 3] != null)
            || (namespace != null
                && !namespace.equals(elementStack[depth * 3]))
            || !elementStack[depth * 3 + 2].equals(name))
            throw new IllegalArgumentException("</{"+namespace+"}"+name+"> does not match start");

        if (pending) {
            check(true);
            depth--;
        }
        else {
            if (indent[depth + 1]) {
                writer.write("\r\n");
                for (int i = 0; i < depth; i++)
                    writer.write("  ");
            }

            writer.write("</");
            String prefix = elementStack[depth * 3 + 1];
            if (!prefix.isEmpty()) {
                writer.write(prefix);
                writer.write(':');
            }
            writer.write(name);
            writer.write('>');
        }

        nspCounts[depth + 1] = nspCounts[depth];
        return this;
    }

    public String getNamespace() {
        return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3];
    }

    public String getName() {
        return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1];
    }

    public int getDepth() {
        return pending ? depth + 1 : depth;
    }

    //-------mmprog modify for terro serialize-----------------------------------
    private boolean writeUnescaped = false;

    public void setWriteUnescaped(boolean wu){
        writeUnescaped = wu;
    }

    public XmlSerializer text(String text) throws IOException {
        check(false);
        indent[depth] = false;

        if(!writeUnescaped){
            writeEscaped(text, -1);
        }else{
            writer.write(text);
        }
        return this;
    }
    //-----------------------------------------------------------------------------

    public XmlSerializer text(char[] text, int start, int len)
        throws IOException {
        text(new String(text, start, len));
        return this;
    }

    public void cdsect(String data) throws IOException {
        check(false);
        // BEGIN android-changed: ]]> is not allowed within a CDATA,
        // so break and start a new one when necessary.
        data = data.replace("]]>", "]]]]><![CDATA[>");
        char[] chars = data.toCharArray();
        // We also aren't allowed any invalid characters.
        for (char ch : chars) {
            boolean valid = (ch >= 0x20 && ch <= 0xd7ff) ||
                    (ch == '\t' || ch == '\n' || ch == '\r') ||
                    (ch >= 0xe000 && ch <= 0xfffd);
            if (!valid) {
                reportInvalidCharacter(ch);
            }
        }
        writer.write("<![CDATA[");
        writer.write(chars, 0, chars.length);
        writer.write("]]>");
        // END android-changed
    }

    public void comment(String comment) throws IOException {
        check(false);
        writer.write("<!--");
        writer.write(comment);
        writer.write("-->");
    }

    public void processingInstruction(String pi)
        throws IOException {
        check(false);
        writer.write("<?");
        writer.write(pi);
        writer.write("?>");
    }
}

//-----------------------------------------------------------------------------------------

class TerroSerializationEnvelope extends SoapSerializationEnvelope {

    private String myXmlString = null;

    public TerroSerializationEnvelope(int version) {
        super(version);
    }

    public void setOutputString(String o){
        myXmlString = o;
    }

    @Override
    public void writeBody(XmlSerializer writer) throws IOException {
        if (encodingStyle != null) {
            writer.attribute(env, "encodingStyle", encodingStyle);
        }

        if(myXmlString==null){
            ((Node) bodyOut).write(writer);
        }else{
            ((TerroKXmlSerializer)writer).setWriteUnescaped(true);
            writer.text(myXmlString);
            ((TerroKXmlSerializer)writer).setWriteUnescaped(false);
        }
    }
}

//-----------------------------------------------------------------------------------------

class TerroHttpTransportSE extends HttpTransportSE {

    private int bufferLength = ServiceConnection.DEFAULT_BUFFER_SIZE;
    private String myXmlVersionTag="";

    public TerroHttpTransportSE(String url) {
        super(url);
    }

    @Override
    public void setXmlVersionTag(String tag) {
        myXmlVersionTag = tag;
        super.setXmlVersionTag(tag);
    }

    @Override
    protected byte[] createRequestData(SoapEnvelope envelope, String encoding)
            throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(bufferLength);
        byte result[] = null;
        bos.write(myXmlVersionTag.getBytes());
        XmlSerializer xw = new TerroKXmlSerializer();

        final Iterator keysIter = getPrefixes().keySet().iterator();

        xw.setOutput(bos, encoding);
        while (keysIter.hasNext()) {
            String key = (String) keysIter.next();
            xw.setPrefix(key, (String) getPrefixes().get(key));
        }
        envelope.write(xw);
        xw.flush();
        bos.write('\r');
        bos.write('\n');
        bos.flush();
        result = bos.toByteArray();
        xw = null;
        bos = null;
        return result;
    }

}
/**
*版权所有(c)2006,James Seigel,加拿大卡尔加里
*版权所有(c)20032004,Stefan Haustein,Oberhausen,Rhld.,德国
* 
*有关完整的许可证,请参阅上面帖子中包含的链接
**/
类TerroKXmlSerializer实现XmlSerializer{
//静态最终字符串未定义=“:”;
//开始添加android
/**写入缓冲区的大小(以字符为单位)*/
私有静态最终整型写入缓冲区大小=500;
//最后添加了android
//开始更改android
//(确保写入程序始终处于缓冲状态。)
私有缓冲写入程序;
//结束android更改
私有布尔未决;
私家车;
私有整数深度;
私有字符串[]elementStack=新字符串[12];
//nsp/前缀/名称
私有整数[]nspCounts=新整数[4];
私有字符串[]nspStack=新字符串[8];
//前缀/nsp;两者均为空“”
私有布尔值[]缩进=新布尔值[4];
私有布尔unicode;
私有字符串编码;
私有最终无效检查(布尔关闭)引发IOException{
如果(!待定)
返回;
深度++;
未决=假;
如果(缩进长度):“>”;
}
private final void writeEscaped(字符串s,int quot)引发IOException{
对于(int i=0;i”:
作者:写(“”);
打破
CDATA中不允许使用“大小写”,
//所以,在必要的时候,中断并开始一个新的。
数据=数据。替换(“]]>”,“]]]>”;
char[]chars=data.toCharArray();
//我们也不允许使用任何无效字符。
for(char ch:chars){

boolean valid=(ch>=0x20&&ch=0xe000&&ch我认为您必须尝试不同的方法。ksoap2从头到尾都在使用org.xmlpull的接口XmlSerializer。XmlSerializer在内部转义字符。对象取自android的XmlPullParserFactory。保留它-节省您的时间。
/** 
 * Copyright (c) 2006, James Seigel, Calgary, AB., Canada
 * Copyright (c) 2003,2004, Stefan Haustein, Oberhausen, Rhld., Germany
 * 
 * For full licences see links that are included in post above
**/
class TerroKXmlSerializer implements XmlSerializer {

    //    static final String UNDEFINED = ":";

    // BEGIN android-added
    /** size (in characters) for the write buffer */
    private static final int WRITE_BUFFER_SIZE = 500;
    // END android-added

    // BEGIN android-changed
    // (Guarantee that the writer is always buffered.)
    private BufferedWriter writer;
    // END android-changed

    private boolean pending;
    private int auto;
    private int depth;

    private String[] elementStack = new String[12];
    //nsp/prefix/name
    private int[] nspCounts = new int[4];
    private String[] nspStack = new String[8];
    //prefix/nsp; both empty are ""
    private boolean[] indent = new boolean[4];
    private boolean unicode;
    private String encoding;

    private final void check(boolean close) throws IOException {
        if (!pending)
            return;

        depth++;
        pending = false;

        if (indent.length <= depth) {
            boolean[] hlp = new boolean[depth + 4];
            System.arraycopy(indent, 0, hlp, 0, depth);
            indent = hlp;
        }
        indent[depth] = indent[depth - 1];

        for (int i = nspCounts[depth - 1]; i < nspCounts[depth]; i++) {
            writer.write(' ');
            writer.write("xmlns");
            if (!nspStack[i * 2].isEmpty()) {
                writer.write(':');
                writer.write(nspStack[i * 2]);
            }
            else if (getNamespace().isEmpty() && !nspStack[i * 2 + 1].isEmpty())
                throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
            writer.write("=\"");
            writeEscaped(nspStack[i * 2 + 1], '"');
            writer.write('"');
        }

        if (nspCounts.length <= depth + 1) {
            int[] hlp = new int[depth + 8];
            System.arraycopy(nspCounts, 0, hlp, 0, depth + 1);
            nspCounts = hlp;
        }

        nspCounts[depth + 1] = nspCounts[depth];
        //   nspCounts[depth + 2] = nspCounts[depth];

        writer.write(close ? " />" : ">");
    }

    private final void writeEscaped(String s, int quot) throws IOException {
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
                case '\n':
                case '\r':
                case '\t':
                    if(quot == -1)
                        writer.write(c);
                    else
                        writer.write("&#"+((int) c)+';');
                    break;
                case '&' :
                    writer.write("&amp;");
                    break;
                case '>' :
                    writer.write("&gt;");
                    break;
                case '<' :
                    writer.write("&lt;");
                    break;
                default:
                    if (c == quot) {
                        writer.write(c == '"' ? "&quot;" : "&apos;");
                        break;
                    }
                    // BEGIN android-changed: refuse to output invalid characters
                    // See http://www.w3.org/TR/REC-xml/#charsets for definition.
                    // No other Java XML writer we know of does this, but no Java
                    // XML reader we know of is able to parse the bad output we'd
                    // otherwise generate.
                    // Note: tab, newline, and carriage return have already been
                    // handled above.
                    boolean valid = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
                    if (!valid) {
                        reportInvalidCharacter(c);
                    }
                    if (unicode || c < 127) {
                        writer.write(c);
                    } else {
                        writer.write("&#" + ((int) c) + ";");
                    }
                    // END android-changed
            }
        }
    }

    // BEGIN android-added
    private static void reportInvalidCharacter(char ch) {
        throw new IllegalArgumentException("Illegal character (" + Integer.toHexString((int) ch) + ")");
    }
    // END android-added

    /*
        private final void writeIndent() throws IOException {
            writer.write("\r\n");
            for (int i = 0; i < depth; i++)
                writer.write(' ');
        }*/

    public void docdecl(String dd) throws IOException {
        writer.write("<!DOCTYPE");
        writer.write(dd);
        writer.write(">");
    }

    public void endDocument() throws IOException {
        while (depth > 0) {
            endTag(elementStack[depth * 3 - 3], elementStack[depth * 3 - 1]);
        }
        flush();
    }

    public void entityRef(String name) throws IOException {
        check(false);
        writer.write('&');
        writer.write(name);
        writer.write(';');
    }

    public boolean getFeature(String name) {
        //return false;
        return (
            "http://xmlpull.org/v1/doc/features.html#indent-output"
                .equals(
                name))
            ? indent[depth]
            : false;
    }

    public String getPrefix(String namespace, boolean create) {
        try {
            return getPrefix(namespace, false, create);
        }
        catch (IOException e) {
            throw new RuntimeException(e.toString());
        }
    }

    private final String getPrefix(
        String namespace,
        boolean includeDefault,
        boolean create)
        throws IOException {

        for (int i = nspCounts[depth + 1] * 2 - 2;
            i >= 0;
            i -= 2) {
            if (nspStack[i + 1].equals(namespace)
                && (includeDefault || !nspStack[i].isEmpty())) {
                String cand = nspStack[i];
                for (int j = i + 2;
                    j < nspCounts[depth + 1] * 2;
                    j++) {
                    if (nspStack[j].equals(cand)) {
                        cand = null;
                        break;
                    }
                }
                if (cand != null)
                    return cand;
            }
        }

        if (!create)
            return null;

        String prefix;

        if (namespace.isEmpty())
            prefix = "";
        else {
            do {
                prefix = "n" + (auto++);
                for (int i = nspCounts[depth + 1] * 2 - 2;
                    i >= 0;
                    i -= 2) {
                    if (prefix.equals(nspStack[i])) {
                        prefix = null;
                        break;
                    }
                }
            }
            while (prefix == null);
        }

        boolean p = pending;
        pending = false;
        setPrefix(prefix, namespace);
        pending = p;
        return prefix;
    }

    public Object getProperty(String name) {
        throw new RuntimeException("Unsupported property");
    }

    public void ignorableWhitespace(String s)
        throws IOException {
        text(s);
    }

    public void setFeature(String name, boolean value) {
        if ("http://xmlpull.org/v1/doc/features.html#indent-output"
            .equals(name)) {
            indent[depth] = value;
        }
        else
            throw new RuntimeException("Unsupported Feature");
    }

    public void setProperty(String name, Object value) {
        throw new RuntimeException(
            "Unsupported Property:" + value);
    }

    public void setPrefix(String prefix, String namespace)
        throws IOException {

        check(false);
        if (prefix == null)
            prefix = "";
        if (namespace == null)
            namespace = "";

        String defined = getPrefix(namespace, true, false);

        // boil out if already defined

        if (prefix.equals(defined))
            return;

        int pos = (nspCounts[depth + 1]++) << 1;

        if (nspStack.length < pos + 1) {
            String[] hlp = new String[nspStack.length + 16];
            System.arraycopy(nspStack, 0, hlp, 0, pos);
            nspStack = hlp;
        }

        nspStack[pos++] = prefix;
        nspStack[pos] = namespace;
    }

    public void setOutput(Writer writer) {
        // BEGIN android-changed
        // Guarantee that the writer is always buffered.
        if (writer instanceof BufferedWriter) {
            this.writer = (BufferedWriter) writer;
        } else {
            this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE);
        }
        // END android-changed

        // elementStack = new String[12]; //nsp/prefix/name
        //nspCounts = new int[4];
        //nspStack = new String[8]; //prefix/nsp
        //indent = new boolean[4];

        nspCounts[0] = 2;
        nspCounts[1] = 2;
        nspStack[0] = "";
        nspStack[1] = "";
        nspStack[2] = "xml";
        nspStack[3] = "http://www.w3.org/XML/1998/namespace";
        pending = false;
        auto = 0;
        depth = 0;

        unicode = false;
    }

    public void setOutput(OutputStream os, String encoding)
        throws IOException {
        if (os == null)
            throw new IllegalArgumentException("os == null");
        setOutput(
            encoding == null
                ? new OutputStreamWriter(os)
                : new OutputStreamWriter(os, encoding));
        this.encoding = encoding;
        if (encoding != null && encoding.toLowerCase(Locale.US).startsWith("utf")) {
            unicode = true;
        }
    }

    public void startDocument(String encoding, Boolean standalone) throws IOException {
        writer.write("<?xml version='1.0' ");

        if (encoding != null) {
            this.encoding = encoding;
            if (encoding.toLowerCase(Locale.US).startsWith("utf")) {
                unicode = true;
            }
        }

        if (this.encoding != null) {
            writer.write("encoding='");
            writer.write(this.encoding);
            writer.write("' ");
        }

        if (standalone != null) {
            writer.write("standalone='");
            writer.write(
                standalone.booleanValue() ? "yes" : "no");
            writer.write("' ");
        }
        writer.write("?>");
    }

    public XmlSerializer startTag(String namespace, String name)
        throws IOException {
        check(false);

        //        if (namespace == null)
        //            namespace = "";

        if (indent[depth]) {
            writer.write("\r\n");
            for (int i = 0; i < depth; i++)
                writer.write("  ");
        }

        int esp = depth * 3;

        if (elementStack.length < esp + 3) {
            String[] hlp = new String[elementStack.length + 12];
            System.arraycopy(elementStack, 0, hlp, 0, esp);
            elementStack = hlp;
        }

        String prefix =
            namespace == null
                ? ""
                : getPrefix(namespace, true, true);

        if (namespace != null && namespace.isEmpty()) {
            for (int i = nspCounts[depth];
                i < nspCounts[depth + 1];
                i++) {
                if (nspStack[i * 2].isEmpty() && !nspStack[i * 2 + 1].isEmpty()) {
                    throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
                }
            }
        }

        elementStack[esp++] = namespace;
        elementStack[esp++] = prefix;
        elementStack[esp] = name;

        writer.write('<');
        if (!prefix.isEmpty()) {
            writer.write(prefix);
            writer.write(':');
        }

        writer.write(name);

        pending = true;

        return this;
    }

    public XmlSerializer attribute(
        String namespace,
        String name,
        String value)
        throws IOException {
        if (!pending)
            throw new IllegalStateException("illegal position for attribute");

        //        int cnt = nspCounts[depth];

        if (namespace == null)
            namespace = "";

        //        depth--;
        //        pending = false;

        String prefix =
            namespace.isEmpty()
                ? ""
                : getPrefix(namespace, false, true);

        //        pending = true;
        //        depth++;

        /*        if (cnt != nspCounts[depth]) {
                    writer.write(' ');
                    writer.write("xmlns");
                    if (nspStack[cnt * 2] != null) {
                        writer.write(':');
                        writer.write(nspStack[cnt * 2]);
                    }
                    writer.write("=\"");
                    writeEscaped(nspStack[cnt * 2 + 1], '"');
                    writer.write('"');
                }
                */

        writer.write(' ');
        if (!prefix.isEmpty()) {
            writer.write(prefix);
            writer.write(':');
        }
        writer.write(name);
        writer.write('=');
        char q = value.indexOf('"') == -1 ? '"' : '\'';
        writer.write(q);
        writeEscaped(value, q);
        writer.write(q);

        return this;
    }

    public void flush() throws IOException {
        check(false);
        writer.flush();
    }
    /*
        public void close() throws IOException {
            check();
            writer.close();
        }
    */
    public XmlSerializer endTag(String namespace, String name)
        throws IOException {

        if (!pending)
            depth--;
        //        if (namespace == null)
        //          namespace = "";

        if ((namespace == null
            && elementStack[depth * 3] != null)
            || (namespace != null
                && !namespace.equals(elementStack[depth * 3]))
            || !elementStack[depth * 3 + 2].equals(name))
            throw new IllegalArgumentException("</{"+namespace+"}"+name+"> does not match start");

        if (pending) {
            check(true);
            depth--;
        }
        else {
            if (indent[depth + 1]) {
                writer.write("\r\n");
                for (int i = 0; i < depth; i++)
                    writer.write("  ");
            }

            writer.write("</");
            String prefix = elementStack[depth * 3 + 1];
            if (!prefix.isEmpty()) {
                writer.write(prefix);
                writer.write(':');
            }
            writer.write(name);
            writer.write('>');
        }

        nspCounts[depth + 1] = nspCounts[depth];
        return this;
    }

    public String getNamespace() {
        return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3];
    }

    public String getName() {
        return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1];
    }

    public int getDepth() {
        return pending ? depth + 1 : depth;
    }

    //-------mmprog modify for terro serialize-----------------------------------
    private boolean writeUnescaped = false;

    public void setWriteUnescaped(boolean wu){
        writeUnescaped = wu;
    }

    public XmlSerializer text(String text) throws IOException {
        check(false);
        indent[depth] = false;

        if(!writeUnescaped){
            writeEscaped(text, -1);
        }else{
            writer.write(text);
        }
        return this;
    }
    //-----------------------------------------------------------------------------

    public XmlSerializer text(char[] text, int start, int len)
        throws IOException {
        text(new String(text, start, len));
        return this;
    }

    public void cdsect(String data) throws IOException {
        check(false);
        // BEGIN android-changed: ]]> is not allowed within a CDATA,
        // so break and start a new one when necessary.
        data = data.replace("]]>", "]]]]><![CDATA[>");
        char[] chars = data.toCharArray();
        // We also aren't allowed any invalid characters.
        for (char ch : chars) {
            boolean valid = (ch >= 0x20 && ch <= 0xd7ff) ||
                    (ch == '\t' || ch == '\n' || ch == '\r') ||
                    (ch >= 0xe000 && ch <= 0xfffd);
            if (!valid) {
                reportInvalidCharacter(ch);
            }
        }
        writer.write("<![CDATA[");
        writer.write(chars, 0, chars.length);
        writer.write("]]>");
        // END android-changed
    }

    public void comment(String comment) throws IOException {
        check(false);
        writer.write("<!--");
        writer.write(comment);
        writer.write("-->");
    }

    public void processingInstruction(String pi)
        throws IOException {
        check(false);
        writer.write("<?");
        writer.write(pi);
        writer.write("?>");
    }
}

//-----------------------------------------------------------------------------------------

class TerroSerializationEnvelope extends SoapSerializationEnvelope {

    private String myXmlString = null;

    public TerroSerializationEnvelope(int version) {
        super(version);
    }

    public void setOutputString(String o){
        myXmlString = o;
    }

    @Override
    public void writeBody(XmlSerializer writer) throws IOException {
        if (encodingStyle != null) {
            writer.attribute(env, "encodingStyle", encodingStyle);
        }

        if(myXmlString==null){
            ((Node) bodyOut).write(writer);
        }else{
            ((TerroKXmlSerializer)writer).setWriteUnescaped(true);
            writer.text(myXmlString);
            ((TerroKXmlSerializer)writer).setWriteUnescaped(false);
        }
    }
}

//-----------------------------------------------------------------------------------------

class TerroHttpTransportSE extends HttpTransportSE {

    private int bufferLength = ServiceConnection.DEFAULT_BUFFER_SIZE;
    private String myXmlVersionTag="";

    public TerroHttpTransportSE(String url) {
        super(url);
    }

    @Override
    public void setXmlVersionTag(String tag) {
        myXmlVersionTag = tag;
        super.setXmlVersionTag(tag);
    }

    @Override
    protected byte[] createRequestData(SoapEnvelope envelope, String encoding)
            throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(bufferLength);
        byte result[] = null;
        bos.write(myXmlVersionTag.getBytes());
        XmlSerializer xw = new TerroKXmlSerializer();

        final Iterator keysIter = getPrefixes().keySet().iterator();

        xw.setOutput(bos, encoding);
        while (keysIter.hasNext()) {
            String key = (String) keysIter.next();
            xw.setPrefix(key, (String) getPrefixes().get(key));
        }
        envelope.write(xw);
        xw.flush();
        bos.write('\r');
        bos.write('\n');
        bos.flush();
        result = bos.toByteArray();
        xw = null;
        bos = null;
        return result;
    }

}