├── .gitignore
├── build.gradle
├── doc
├── about.html
├── development.html
├── documentation.html
├── license.html
└── samples.html
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── jitpack.yml
├── license.txt
├── readme.md
├── samples
├── EventList.java
├── KDomRoundtrip.java
├── LongStringTest.java
├── Roundtrip.java
├── WbxmlRoundtrip.java
├── Weblogs.java
├── YesNoGame.java
├── bogdan.xml
├── sample.xml
└── simple.xml
├── samples_midp
└── Newsreader.java
├── settings.gradle
└── src
├── main
├── java
│ ├── module-info.java
│ └── org
│ │ └── kxml2
│ │ ├── io
│ │ ├── KXmlParser.java
│ │ └── KXmlSerializer.java
│ │ ├── kdom
│ │ ├── Document.java
│ │ ├── Element.java
│ │ └── Node.java
│ │ └── wap
│ │ ├── Wbxml.java
│ │ ├── WbxmlParser.java
│ │ ├── WbxmlSerializer.java
│ │ ├── syncml
│ │ └── SyncML.java
│ │ ├── wml
│ │ └── Wml.java
│ │ └── wv
│ │ └── WV.java
└── resources
│ └── META-INF
│ └── services
│ └── org.xmlpull.v1.XmlPullParserFactory
└── test
└── java
└── TestWb.java
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | .gradle/
3 | .idea/
4 | target/
5 | out/
6 | .project
7 | .classpath
8 | /bootstrap.xml
9 | /font-awesome.xml
10 | *.*~
11 | *.iml
12 | **/*.iml
13 | *.ipl
14 | **/*.ipl
15 | *.iwl
16 | **/*.iwl
17 | /logs
18 | *.log
19 | config.properties
20 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'maven'
3 |
4 | group = 'com.github.stefanhaustein'
5 | version = '2.5.0'
6 |
7 | java {
8 | modularity.inferModulePath.set(true)
9 | sourceCompatibility = JavaVersion.VERSION_1_9
10 | targetCompatibility = JavaVersion.VERSION_1_9
11 | }
12 |
13 | // This is in case we ever use non-ASCII chars in sources
14 | compileJava.options.encoding = 'UTF-8'
15 | compileTestJava.options.encoding = 'UTF-8'
16 |
17 | repositories {
18 | mavenLocal()
19 | maven {
20 | url "https://dl.bintray.com/unverbraucht/java9-fixed-jars"
21 | }
22 | }
23 |
24 | dependencies {
25 | implementation(group: 'org.xmlpull', name: 'xmlpull', version: '1.1.4.0')
26 | testImplementation(group: 'junit', name: 'junit', version: '4.12')
27 | }
28 |
29 | task sourcesJar(type: Jar, dependsOn: classes) {
30 | classifier 'sources'
31 | from sourceSets.main.allSource
32 | }
33 |
34 | artifacts {
35 | archives sourcesJar
36 | }
37 |
--------------------------------------------------------------------------------
/doc/about.html:
--------------------------------------------------------------------------------
1 |
2 |
About kXML
3 |
4 |
5 |
6 |
7 |
8 | About kXML
9 |
10 | kXML is a small XML pull parser, specially designed for constrained environments such as Applets, Personal Java or MIDP devices. In contrast to kXML 1, kXML 2 is based on the common
11 | XML pull API.
12 |
13 |
14 | Pull based XML parsing combines some of the advantages of SAX and DOM:
15 |
16 |
17 |
18 | - In contrast to push parsers (SAX), pull parsers such as kXML make it possible to model the
19 | XML processing routines after the structure of the processed XML document. Events processing
20 | is similar to an InputStream. If a part of the stream requires special handling, the parser
21 | can simply be delegated to a specialized method by handing over the parser.
22 |
23 | - While the above is also possible with an explicit DOM, DOM usually requires that the whole
24 | document structure is present in main memory.
25 |
26 | - In contrast to DOM based parsing, the XML events are accessible immediately when they
27 | are available, it is not necessary to wait for the whole tree to build up.
28 |
29 |
30 |
31 |
32 | kXML History and Versions
33 |
34 |
35 |
36 | XP |
37 | XP was the predecessor of kXML, a simple wrapper that turned a given SAX parser
38 | into a pull parser.
39 | XP was originally implemented to simplify message (de)serialization in the Infolayer project,
40 | which is quite cumbersome with push parsers (SAX). XP was initially released at 1999-12-25. |
41 |
42 |
43 | kXML1 |
44 | To use the pull parser on embedded devices, it was necessary to get
45 | rid of the SAX dependency. kXML1 is a simple pull parser, based on event objects.
46 | kXML1 is now deprecated, please use kXML2 instead. kXML1 is archieved at
47 | kxml.objectweb.org. The initial public release
48 | of kXML 1 was at 2000-07-25. |
49 |
50 |
51 | kXML2 |
52 | The current version of kXML. In contrast to kXML1, it features cursor
53 | API instead of event objects, leading to a reduced footprint and less object
54 | creation overhead. kXML 2 is released under the BSD license. |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | XML Conformance
63 |
64 | In order to keep kXML as small as possible, no efforts are made to recognize certain well-formedness errors that would require additional detection code, such as
65 |
66 |
67 | - ']]>' contained in text content,
68 | - duplicate attributes, and
69 | - <? folowed by a space before the target.
70 |
71 |
72 | Thus, kXML will accept some XML documents that should actually be rejected. Of course, an XML parser should detect all syntax errors to discourage the creation of bogous documents that work with one parser and do not work with another. Thus, if you are not limited by memory constraints, please use MXP, which is also faster than kXML.
73 |
74 |
75 | (C) 1999-2005 Stefan Haustein
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/doc/development.html:
--------------------------------------------------------------------------------
1 |
2 | kXML Development
3 |
4 | The development resources of the kXML project (mailing list, CVS repository, files) are hosted at
5 | sourceforge.net:
6 |
7 |
10 |
11 | If you experience any bugs or incompatibilities, please try the
12 | latest version from CVS before filing a bug report -- a fix may be
13 | available there already.
14 |
15 |
16 |
--------------------------------------------------------------------------------
/doc/documentation.html:
--------------------------------------------------------------------------------
1 | kXML 2 Documentation
2 |
3 |
4 | kXML 2 implements the XmlPull API. Please find general information about
5 | XmlPull parsers including the interface documentation at
6 | xmlpull.org.
7 |
8 | Naveen Balani has written a nice
10 | introduction to kxml 2 for IBM Developer Works.
11 |
12 | For kXML specific classes, in particular for WBXML, please refer
13 | to the kXML API Documentation:
14 |
17 |
18 |
19 | Special Features
20 |
21 | kXML has two "special" features that are intended to simplify developers' life in constrained environments:
22 |
23 |
24 | - Support for WBXML (WAP binary encoded XML): Allows to parse WAP or Wireless Village content
25 | - A robust "relaxed" mode for parsing HTML or SGML files (that are not well-formed XML documents) in order to avoid
26 | the need of two separate parsers in mobile phones.
27 |
28 |
29 |
30 | Recommended Calling Conventions
31 |
32 | When handing an XMLpull parser to subroutines, it is recommended that the current
33 | position is on a start tag (allowing the subroutine to analyze the attributes).
34 | The post condition should usually be that the current position is the matching end tag.
35 |
36 |
37 | Parsing Element-Only and Text-Only Content
38 |
39 | General XML content can be parsed with the XML pull API using a loop advanving
40 | to the next event and a switch statement that depends on the event type. However,
41 | when using XML for data transfer (in contrast to text documents), most XML elements
42 | contain either only text or only other elements (possibly with further sub-elements).
43 | For those common cases, the parsing process can be simplified significantly by
44 | using the XmlPull API methods nextTag and nextText.
45 |
46 | Additionally, the method require() may optionally be used to assert a
47 | certain parser state. The following sample illustrates both situations and methods.
48 | The outer element elements has element-only content; the contained
49 | text-elements have text-only content:
50 |
51 |
52 | <elements>
53 | <text>text1</text>
54 | <text>text2</text>
55 | </elements>
56 |
57 |
58 | Parsing Code
59 |
60 | parser.nextTag();
61 | parser.require(XmlPullParser.START_TAG, null, "elements");
62 |
63 | while(parser.nextTag() == XmlPullParser.START_TAG) {
64 | parser.require(XmlPullParser.START_TAG, null, "text");
65 |
66 | // handle element content
67 | System.out.println("text content: "+ parser.nextText());
68 |
69 | parser.require(XmlPullParser.END_TAG, null, "text");
70 | }
71 |
72 | parser.require(XmlPullParser.END_TAG, null, "elements");
73 |
74 |
75 | nextTag() advances to the next
76 | start or end tag, skipping insignificant events such as white space,
77 | comments and PIs. nextText() requires that the current position
78 | is a start tag. It returns the text content of the corresponding element.
79 | The post condition is that the current position is an end tag.
80 | Please note that the calls require() are optional assertions,
81 | they may be left out completely.
82 |
83 |
84 | Articles about kXML 1 and 2
85 |
86 |
87 |
88 | 2003-09-01 |
89 | New article about
90 | kXML 2 written by Naveen Balani published at IBM Developer Works |
91 |
92 |
93 |
94 | 2003-04-04 |
95 | New article about kXML 1 written by Robert Cadenaat published at DevX |
96 |
97 |
98 | 2002-03-25 |
99 | New article about kXML and WBXML comprssion
100 | written by Eric Giguere available at the SUN developer connection |
101 |
102 |
103 | 2002-03-07 |
104 | New artikle about kXML 1
105 | written by Jonathan Knudsen available at the SUN developer connection |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/doc/license.html:
--------------------------------------------------------------------------------
1 | kXML License
2 |
3 | kXML is licensed under the BSD license (see below). Please note that
4 | the BSD license mandates to keep the copyright note when including
5 | kXML in own projects. If you are using kXML in your own project
6 | (open source or not), please let us know, so we can link it at our
7 | samples page.
8 |
9 |
10 | Copyright (c) 2002-2007 Stefan Haustein, Oberhausen, Rhld., Germany
11 |
12 | Permission is hereby granted, free of charge, to any person obtaining a copy
13 | of this software and associated documentation files (the "Software"), to deal
14 | in the Software without restriction, including without limitation the rights
15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 | sell copies of the Software, and to permit persons to whom the Software is
17 | furnished to do so, subject to the following conditions:
18 |
19 | The above copyright notice and this permission notice shall be included in
20 | all copies or substantial portions of the Software.
21 |
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 | IN THE SOFTWARE.
29 |
--------------------------------------------------------------------------------
/doc/samples.html:
--------------------------------------------------------------------------------
1 |
2 | kXML Samples
3 |
4 | Some small code snippets illustrating basic parsing operations can be examined via
5 | viewcvs:
6 |
9 |
10 | There are also some nice open source projects built on kXML that illustrate how to use the parser:
11 |
12 | - RSS Reader - a MIDP RSS reader using kXML 2.1.7
13 | - Azure - a free blog client for your phone and PDA
14 |
15 |
16 | If you are using kXML in your own project
17 | (open source or not), please let us know, so we can link to it here.
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kobjects/kxml2/8ab596248a9c70c8cafe286efb013642cc821d11/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/jitpack.yml:
--------------------------------------------------------------------------------
1 | jdk:
2 | - openjdk9
3 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | sell copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | IN THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # README
2 | - Interested in Kotlin? Try [KtXml](https://github.com/kobjects/ktxml) and provide feedback!
3 | - Now the content of `org.xmlpull.v1.XmlPullParserFactory` is split across multiple lines `org.kxml2.io.KXmlParser` & `org.kxml2.io.KXmlSerializer` instead of comma separated `org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer` which bombs in Java 9+. This fix will ensure java 9 module system will atleast no complain. Even with this fix, implementation of `XmlPullParserFactory` in `xmlpull` is still nothing but abuse of `ServiceLoader` implementation. But atleast it does not bomb right now
4 | - Library can be added as a dependency using
5 |
6 | ```groovy
7 | repositories {
8 | mavenCentral()
9 | maven {
10 | url "https://jitpack.io" // maven repo where the current library resides
11 | }
12 | maven {
13 | url "https://dl.bintray.com/unverbraucht/java9-fixed-jars" // repo for fetching `xmlpull` dependency that's java 9 enabled
14 | }
15 | }
16 |
17 | dependencies {
18 | implementation("com.github.kobjects:kxml2:")
19 | }
20 | ```
21 |
--------------------------------------------------------------------------------
/samples/EventList.java:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 |
3 | import org.kxml2.io.*;
4 | import org.xmlpull.v1.*;
5 |
6 | public class EventList {
7 |
8 | public static void main(String[] args)
9 | throws IOException, XmlPullParserException {
10 |
11 | for (int i = 0; i < 2; i++) {
12 |
13 | XmlPullParser xr = new KXmlParser();
14 | xr.setInput(new FileReader(args[0]));
15 |
16 | System.out.println("");
17 | System.out.println(
18 | "*** next" + (i == 0 ? "Token" : "") + " () event list ***");
19 | System.out.println("");
20 |
21 | do {
22 | if (i == 0)
23 | xr.nextToken();
24 | else
25 | xr.next();
26 |
27 | System.out.println(xr.getPositionDescription());
28 |
29 |
30 | } while (xr.getEventType() != XmlPullParser.END_DOCUMENT);
31 | }
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/samples/KDomRoundtrip.java:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 |
3 | import org.xmlpull.v1.*;
4 | import org.kxml2.kdom.*;
5 | import org.kxml2.io.*;
6 |
7 |
8 | /**
9 | * @author Stefan Haustein
10 | *
11 | * To change this generated comment edit the template variable "typecomment":
12 | * Window>Preferences>Java>Templates.
13 | */
14 |
15 | public class KDomRoundtrip {
16 |
17 | /**
18 | * Constructor for KDomRoundtrip.
19 | */
20 |
21 |
22 | public static void main(String[] args) throws IOException, XmlPullParserException {
23 | if (args.length == 0) throw new RuntimeException ("input url expected");
24 | for (int i = 0; i < args.length; i++) {
25 | System.out.println ("generating KDom from "+args[i]);
26 |
27 | KXmlParser parser = new KXmlParser ();
28 | parser.setInput (new FileReader (args [i]));
29 | parser.setFeature (XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
30 |
31 | Document doc = new Document ();
32 | doc.parse (parser);
33 |
34 | KXmlSerializer serializer = new KXmlSerializer ();
35 | serializer.setOutput (System.out, null);
36 |
37 | doc.write (serializer);
38 | serializer.flush ();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/samples/LongStringTest.java:
--------------------------------------------------------------------------------
1 |
2 | import org.xmlpull.v1.XmlPullParser;
3 | import org.kxml2.io.KXmlParser;
4 | import java.io.ByteArrayInputStream;
5 | import java.io.InputStreamReader;
6 |
7 | // (C) Michael Walker, sun.com
8 |
9 | public class LongStringTest {
10 |
11 |
12 | public static void main(String[] args) {
13 | String xmlStr = ""
14 | + ""
15 | + ""
16 | + ""
17 | + ""
18 | + ""
19 | + ""
20 | + "";
21 | System.out.println("xmlStr length: " + xmlStr.length());
22 |
23 | ByteArrayInputStream bais = new ByteArrayInputStream(xmlStr.getBytes());
24 | InputStreamReader isr = new InputStreamReader(bais);
25 |
26 | try {
27 | KXmlParser parser = new KXmlParser();
28 | parser.setInput(isr);
29 | while (parser.next() != XmlPullParser.END_DOCUMENT) {
30 | if (parser.getEventType() == XmlPullParser.START_TAG) {
31 | System.out.println("start tag: " + parser.getName());
32 | }
33 | }
34 | } catch (Exception ex) {
35 | ex.printStackTrace();
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/samples/Roundtrip.java:
--------------------------------------------------------------------------------
1 |
2 | //package org.xmlpull.v1.samples;
3 |
4 | import java.io.*;
5 |
6 | import org.kxml2.io.*;
7 | import org.xmlpull.v1.*;
8 | public class Roundtrip {
9 | //private static final String FEATURE_XML_ROUNDTRIP=
10 | // "http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
11 |
12 | XmlPullParser parser;
13 | XmlSerializer serializer;
14 |
15 | public Roundtrip(
16 | XmlPullParser parser,
17 | XmlSerializer serializer) {
18 | this.parser = parser;
19 | this.serializer = serializer;
20 | }
21 |
22 | public void writeStartTag()
23 | throws XmlPullParserException, IOException {
24 | //check forcase when feature xml roundtrip is supported
25 | //if (parser.getFeature (FEATURE_XML_ROUNDTRIP)) {
26 | //TODO: how to do pass through string with actual start tag in getText()
27 | //return;
28 | //}
29 | if (!parser
30 | .getFeature(
31 | XmlPullParser
32 | .FEATURE_REPORT_NAMESPACE_ATTRIBUTES)) {
33 | for (int i =
34 | parser.getNamespaceCount(parser.getDepth() - 1);
35 | i
36 | < parser.getNamespaceCount(parser.getDepth())
37 | - 1;
38 | i++) {
39 | serializer.setPrefix(
40 | parser.getNamespacePrefix(i),
41 | parser.getNamespaceUri(i));
42 | }
43 | }
44 | serializer.startTag(
45 | parser.getNamespace(),
46 | parser.getName());
47 |
48 | for (int i = 0; i < parser.getAttributeCount(); i++) {
49 | serializer.attribute(
50 | parser.getAttributeNamespace(i),
51 | parser.getAttributeName(i),
52 | parser.getAttributeValue(i));
53 | }
54 | //serializer.closeStartTag();
55 | }
56 |
57 | public void writeToken()
58 | throws XmlPullParserException, IOException {
59 | switch (parser.getEventType()) {
60 | case XmlPullParser.START_DOCUMENT :
61 | serializer.startDocument (null, null);
62 | break;
63 |
64 | case XmlPullParser.END_DOCUMENT :
65 | serializer.endDocument();
66 | break;
67 |
68 | case XmlPullParser.START_TAG :
69 | writeStartTag();
70 | break;
71 |
72 | case XmlPullParser.END_TAG :
73 | serializer.endTag(
74 | parser.getNamespace(),
75 | parser.getName());
76 | break;
77 |
78 | case XmlPullParser.IGNORABLE_WHITESPACE :
79 | //comment it to remove ignorable whtespaces from XML infoset
80 | serializer.ignorableWhitespace(parser.getText());
81 | break;
82 |
83 | case XmlPullParser.TEXT :
84 | if(parser.getText() == null)
85 | System.err.println("null text error at: "+parser.getPositionDescription());
86 | else
87 | serializer.text(parser.getText());
88 | break;
89 |
90 | case XmlPullParser.ENTITY_REF :
91 | if(parser.getText() != null)
92 | serializer.text(parser.getText());
93 | else
94 | serializer.entityRef(parser.getName());
95 | break;
96 |
97 | case XmlPullParser.CDSECT :
98 | serializer.cdsect(parser.getText());
99 | break;
100 |
101 | case XmlPullParser.PROCESSING_INSTRUCTION :
102 | serializer.processingInstruction(
103 | parser.getText());
104 | break;
105 |
106 | case XmlPullParser.COMMENT :
107 | serializer.comment(parser.getText());
108 | break;
109 |
110 | case XmlPullParser.DOCDECL :
111 | serializer.docdecl(parser.getText());
112 | break;
113 |
114 | default :
115 | throw new RuntimeException(
116 | "unrecognized event: "
117 | + parser.getEventType());
118 | }
119 | }
120 |
121 | public void roundTrip()
122 | throws XmlPullParserException, IOException {
123 |
124 | while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
125 | writeToken();
126 | parser.nextToken();
127 | }
128 | writeToken();
129 | serializer.flush();
130 | }
131 |
132 | public static void main(String[] args) throws Exception {
133 | if (args.length == 0)
134 | throw new RuntimeException("input xml file name expected");
135 | for (int i = 0; i < args.length; i++) {
136 | System.out.println("processing: " + args[i]);
137 | XmlPullParser pp = new KXmlParser();
138 | pp.setFeature(
139 | XmlPullParser.FEATURE_PROCESS_NAMESPACES,
140 | true);
141 | XmlSerializer serializer = new KXmlSerializer();
142 |
143 | pp.setInput(new FileReader(args[i]));
144 | serializer.setOutput(System.out, null);
145 |
146 | (new Roundtrip(pp, serializer)).roundTrip();
147 | serializer.flush();
148 | }
149 | }
150 |
151 | }
--------------------------------------------------------------------------------
/samples/WbxmlRoundtrip.java:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 |
3 | import org.kxml2.io.*;
4 | import org.kxml2.wap.*;
5 | import org.xmlpull.v1.*;
6 |
7 | /*
8 | * Created on 25.09.2003
9 | *
10 | * To change the template for this generated file go to
11 | * Window>Preferences>Java>Code Generation>Code and Comments
12 | */
13 |
14 | /**
15 | * @author haustein
16 | *
17 | * To change the template for this generated type comment go to
18 | * Window>Preferences>Java>Code Generation>Code and Comments
19 | */
20 | public class WbxmlRoundtrip {
21 |
22 | public static void main(String[] argv) throws Exception {
23 |
24 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
25 |
26 | XmlPullParser xp = new KXmlParser();
27 | xp.setInput(new FileInputStream(argv[0]), null);
28 | XmlSerializer xs = new WbxmlSerializer();
29 | xs.setOutput(bos, null);
30 |
31 | new Roundtrip(xp, xs).roundTrip();
32 |
33 | byte[] wbxml = bos.toByteArray();
34 |
35 | System.out.println("********* WBXML size: "+wbxml.length+" ***********");
36 |
37 | for(int i = 0; i < wbxml.length; i += 16){
38 | for (int j = i; j < Math.min(i + 16, wbxml.length); j ++) {
39 | int b = ((int) wbxml[j]) & 0x0ff;
40 | System.out.print(Integer.toHexString(b / 16));
41 | System.out.print(Integer.toHexString(b % 16));
42 | System.out.print(' ');
43 | }
44 |
45 | for (int j = i; j < Math.min(i + 16, wbxml.length); j ++) {
46 | int b = wbxml[j];
47 | System.out.print(b >= 32 && b <= 127 ? (char) b : '?');
48 | }
49 |
50 | System.out.println();
51 | }
52 |
53 | ByteArrayInputStream bis = new ByteArrayInputStream(wbxml);
54 |
55 | xp = new WbxmlParser();
56 | xp.setInput(bis, null);
57 |
58 | xs = new KXmlSerializer();
59 | xs.setOutput(System.out, null);
60 |
61 | new Roundtrip(xp, xs).roundTrip();
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/samples/Weblogs.java:
--------------------------------------------------------------------------------
1 | import org.xmlpull.v1.*;
2 |
3 | import java.util.*;
4 | import java.io.*;
5 | import java.net.*;
6 |
7 | /**
8 | * A simple example illustrationg some differences of the XmlPull API
9 | * and SAX. For the corresponding SAX based implementation, please refer to
10 | * http://www.cafeconleche.org/slides/sd2001east/xmlandjava/81.html ff. */
11 |
12 | public class Weblogs {
13 |
14 | static List listChannels()
15 | throws IOException, XmlPullParserException {
16 | return listChannels("http://static.userland.com/weblogMonitor/logs.xml");
17 | }
18 |
19 | static List listChannels(String uri)
20 | throws IOException, XmlPullParserException {
21 |
22 | Vector result = new Vector();
23 |
24 | InputStream is = new URL(uri).openStream();
25 | XmlPullParser parser =
26 | XmlPullParserFactory.newInstance().newPullParser();
27 |
28 | parser.setInput(is, null);
29 |
30 | parser.nextTag();
31 | parser.require(XmlPullParser.START_TAG, "", "weblogs");
32 |
33 | while (parser.nextTag() == XmlPullParser.START_TAG) {
34 | String url = readSingle(parser);
35 | if (url != null)
36 | result.addElement(url);
37 | }
38 | parser.require(XmlPullParser.END_TAG, "", "weblogs");
39 |
40 | parser.next();
41 | parser.require(XmlPullParser.END_DOCUMENT, null, null);
42 |
43 | is.close ();
44 | parser.setInput (null);
45 |
46 | return result;
47 | }
48 |
49 | public static String readSingle(XmlPullParser parser)
50 | throws IOException, XmlPullParserException {
51 |
52 | String url = null;
53 | parser.require(XmlPullParser.START_TAG, "", "log");
54 |
55 | while (parser.nextTag() == XmlPullParser.START_TAG) {
56 | String name = parser.getName();
57 | String content = parser.nextText();
58 | if (name.equals("url"))
59 | url = content;
60 | parser.require(XmlPullParser.END_TAG, "", name);
61 | }
62 | parser.require(XmlPullParser.END_TAG, "", "log");
63 | return url;
64 | }
65 |
66 | public static void main(String[] args)
67 | throws IOException, XmlPullParserException {
68 |
69 | List urls =
70 | args.length > 0
71 | ? listChannels(args[0])
72 | : listChannels();
73 |
74 | for (Iterator i = urls.iterator(); i.hasNext();)
75 | System.out.println(i.next());
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/samples/YesNoGame.java:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Stefan Haustein
3 | *
4 | * To change this generated comment edit the template variable "typecomment":
5 | * Window>Preferences>Java>Templates.
6 | */
7 | import java.io.*;
8 | import org.xmlpull.v1.*;
9 | import org.kxml2.io.*;
10 |
11 | class Node {
12 | private String text;
13 | private Node yes; // if null, it's an answer
14 | private Node no;
15 |
16 | Node(String answer) {
17 | this.text = answer;
18 | }
19 |
20 | Node(String question, Node yes, Node no) {
21 | this.text = question;
22 | this.yes = yes;
23 | this.no = no;
24 | }
25 |
26 | void run () throws IOException {
27 |
28 | if (yes == null)
29 | System.out.println ("Answer: "+text);
30 | else {
31 | System.out.println (text+ " (y/n)");
32 |
33 | while (true) {
34 | int i = System.in.read();
35 | if (i == 'y' || i == 'Y') {
36 | yes.run();
37 | break;
38 | }
39 | else if (i == 'n' || i == 'N') {
40 | no.run();
41 | break;
42 | }
43 | }
44 | }
45 | }
46 |
47 | }
48 |
49 | public class YesNoGame {
50 |
51 | public static Node parseAnswer(XmlPullParser p) throws IOException, XmlPullParserException {
52 | p.require(XmlPullParser.START_TAG, "", "answer");
53 | Node result = new Node (p.nextText());
54 | p.require(XmlPullParser.END_TAG, "", "answer");
55 | return result;
56 | }
57 |
58 | public static Node parseQuestion(XmlPullParser p) throws IOException, XmlPullParserException {
59 | p.require(XmlPullParser.START_TAG, "", "question");
60 | String text = p.getAttributeValue("", "text");
61 | Node yes = parseNode (p);
62 | Node no = parseNode (p);
63 | p.nextTag();
64 | p.require(XmlPullParser.END_TAG, "", "question");
65 | return new Node (text, yes, no);
66 | }
67 |
68 | public static Node parseNode (XmlPullParser p) throws IOException, XmlPullParserException {
69 | p.nextTag ();
70 | p.require(XmlPullParser.START_TAG, "", null);
71 | if (p.getName().equals("question"))
72 | return parseQuestion(p);
73 | else
74 | return parseAnswer(p);
75 | }
76 |
77 |
78 | public static void main(String[] args) throws IOException, XmlPullParserException {
79 | String sample = "\n"
80 | + " \n"
81 | + " It is the Sun!\n"
82 | + " It is a ball!\n"
83 | + " \n"
84 | + " I do not know!\n"
85 | + "\n";
86 |
87 | XmlPullParser p = new KXmlParser();
88 | p.setInput (new StringReader (sample));
89 |
90 | Node game = parseNode (p);
91 |
92 | game.run();
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/samples/bogdan.xml:
--------------------------------------------------------------------------------
1 |
2 | bar
3 |
4 | This is in a new namespace
5 |
6 | (06/15/2004 00:31) <HTML><BODY
7 | bgcolor="#ffffff"><FONT
8 | LANG="0">hiho</FONT></BODY></HTML>
9 |
10 |
--------------------------------------------------------------------------------
/samples/sample.xml:
--------------------------------------------------------------------------------
1 |
2 | bar
3 |
4 | This is in a new namespace
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/simple.xml:
--------------------------------------------------------------------------------
1 |
2 | simple test without namespaces!
3 |
4 | This is in a test text namespace
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/samples_midp/Newsreader.java:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 | import java.util.Vector;
3 |
4 | import org.kxml2.io.*;
5 | import org.xmlpull.v1.*;
6 |
7 | import javax.microedition.midlet.*;
8 | import javax.microedition.lcdui.*;
9 | import javax.microedition.io.*;
10 |
11 | public class Newsreader extends MIDlet implements CommandListener {
12 |
13 | static final String URL = "http://www.newsforge.com/newsforge.xml";
14 | static final String TITLE = "NewsForge";
15 |
16 | Vector descriptions = new Vector();
17 | List newsList = new List(TITLE, Choice.IMPLICIT);
18 | TextBox textBox = new TextBox("", "", 256, TextField.ANY);
19 | Display display;
20 |
21 | Command backCmd = new Command("Back", Command.BACK, 0);
22 |
23 | class ReadThread extends Thread {
24 |
25 | public void run() {
26 | try {
27 | HttpConnection httpConnection = (HttpConnection) Connector.open(URL);
28 |
29 | KXmlParser parser = new KXmlParser();
30 |
31 | parser.setInput(new InputStreamReader(httpConnection.openInputStream()));
32 |
33 | // parser.relaxed = true;
34 |
35 | parser.nextTag();
36 | parser.require(XmlPullParser.START_TAG, null, "backslash");
37 |
38 | while (parser.nextTag () != XmlPullParser.END_TAG)
39 | readStory(parser);
40 |
41 | parser.require(XmlPullParser.END_TAG, null, "backslash");
42 | parser.next();
43 |
44 | parser.require(XmlPullParser.END_DOCUMENT, null, null);
45 | } catch (Exception e) {
46 | e.printStackTrace();
47 | descriptions.addElement(e.toString());
48 | newsList.append("Error", null);
49 | }
50 | }
51 |
52 | /** Read a story and append it to the list */
53 |
54 | void readStory(KXmlParser parser)
55 | throws IOException, XmlPullParserException {
56 |
57 | parser.require(XmlPullParser.START_TAG, null, "story");
58 |
59 | String title = null;
60 | String description = null;
61 |
62 | while (parser.nextTag() != XmlPullParser.END_TAG) {
63 |
64 | parser.require(XmlPullParser.START_TAG, null, null);
65 | String name = parser.getName();
66 |
67 | String text = parser.nextText();
68 |
69 | System.out.println ("<"+name+">"+text);
70 |
71 | if (name.equals("title"))
72 | title = text;
73 | else if (name.equals("description"))
74 | description = text;
75 |
76 | parser.require(XmlPullParser.END_TAG, null, name);
77 | }
78 | parser.require(XmlPullParser.END_TAG, null, "story");
79 |
80 | if (title != null) {
81 | descriptions.addElement(""+description);
82 | newsList.append(title, null);
83 | }
84 | }
85 | }
86 |
87 | public void startApp() {
88 | display = Display.getDisplay(this);
89 | display.setCurrent(newsList);
90 | newsList.setCommandListener(this);
91 | textBox.setCommandListener(this);
92 | textBox.addCommand(backCmd);
93 | new ReadThread().start();
94 | }
95 |
96 | public void pauseApp() {
97 | }
98 |
99 | public void commandAction(Command c, Displayable d) {
100 |
101 | if (c == List.SELECT_COMMAND) {
102 |
103 | String text = (String) descriptions.elementAt(newsList.getSelectedIndex());
104 |
105 | if (textBox.getMaxSize() < text.length())
106 | textBox.setMaxSize(text.length());
107 |
108 | textBox.setString(text);
109 | display.setCurrent(textBox);
110 | } else if (c == backCmd)
111 | display.setCurrent(newsList);
112 | }
113 |
114 | public void destroyApp(boolean really) {
115 | }
116 | /*
117 | public static void main(String[] argv) {
118 | org.me4se.MIDletRunner.main (new String [] {"Newsreader"});
119 | }
120 | */
121 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'kxml2'
2 |
3 |
--------------------------------------------------------------------------------
/src/main/java/module-info.java:
--------------------------------------------------------------------------------
1 | module org.kxml {
2 | exports org.kxml2.io;
3 | exports org.kxml2.kdom;
4 | exports org.kxml2.wap;
5 |
6 | requires org.xmlpull;
7 | }
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/io/KXmlSerializer.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 |
22 | package org.kxml2.io;
23 |
24 | import java.io.*;
25 | import org.xmlpull.v1.*;
26 |
27 | public class KXmlSerializer implements XmlSerializer {
28 |
29 | // static final String UNDEFINED = ":";
30 |
31 | private Writer writer;
32 |
33 | private boolean pending;
34 | private int auto;
35 | private int depth;
36 |
37 | private String[] elementStack = new String[12];
38 | //nsp/prefix/name
39 | private int[] nspCounts = new int[4];
40 | private String[] nspStack = new String[8];
41 | //prefix/nsp; both empty are ""
42 | private boolean[] indent = new boolean[4];
43 | private boolean unicode;
44 | private String encoding;
45 |
46 | private final void check(boolean close) throws IOException {
47 | if (!pending)
48 | return;
49 |
50 | depth++;
51 | pending = false;
52 |
53 | if (indent.length <= depth) {
54 | boolean[] hlp = new boolean[depth + 4];
55 | System.arraycopy(indent, 0, hlp, 0, depth);
56 | indent = hlp;
57 | }
58 | indent[depth] = indent[depth - 1];
59 |
60 | for (int i = nspCounts[depth - 1];
61 | i < nspCounts[depth];
62 | i++) {
63 | writer.write(' ');
64 | writer.write("xmlns");
65 | if (!"".equals(nspStack[i * 2])) {
66 | writer.write(':');
67 | writer.write(nspStack[i * 2]);
68 | }
69 | else if ("".equals(getNamespace()) && !"".equals(nspStack[i * 2 + 1]))
70 | throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
71 | writer.write("=\"");
72 | writeEscaped(nspStack[i * 2 + 1], '"');
73 | writer.write('"');
74 | }
75 |
76 | if (nspCounts.length <= depth + 1) {
77 | int[] hlp = new int[depth + 8];
78 | System.arraycopy(nspCounts, 0, hlp, 0, depth + 1);
79 | nspCounts = hlp;
80 | }
81 |
82 | nspCounts[depth + 1] = nspCounts[depth];
83 | // nspCounts[depth + 2] = nspCounts[depth];
84 |
85 | writer.write(close ? " />" : ">");
86 | }
87 |
88 | private final void writeEscaped(String s, int quot)
89 | throws IOException {
90 |
91 | for (int i = 0; i < s.length(); i++) {
92 | char c = s.charAt(i);
93 | switch (c) {
94 | case '\n':
95 | case '\r':
96 | case '\t':
97 | if(quot == -1)
98 | writer.write(c);
99 | else
100 | writer.write(""+((int) c)+';');
101 | break;
102 | case '&' :
103 | writer.write("&");
104 | break;
105 | case '>' :
106 | writer.write(">");
107 | break;
108 | case '<' :
109 | writer.write("<");
110 | break;
111 | case '"' :
112 | case '\'' :
113 | if (c == quot) {
114 | writer.write(
115 | c == '"' ? """ : "'");
116 | break;
117 | }
118 | default :
119 | //if(c < ' ')
120 | // throw new IllegalArgumentException("Illegal control code:"+((int) c));
121 |
122 | if (i < s.length() - 1) {
123 | char cLow = s.charAt(i + 1);
124 | // c is high surrogate and cLow is low surrogate
125 | if (c >= 0xd800 && c <= 0xdbff && cLow >= 0xdc00 && cLow <= 0xdfff) {
126 | // write surrogate pair as single code point
127 | int n = ((c - 0xd800) << 10) + (cLow - 0xdc00) + 0x010000;
128 | writer.write("" + n + ";");
129 | i++; // Skip the low surrogate
130 | break;
131 | }
132 | // Does nothing smart about orphan surrogates, just output them "as is"
133 | }
134 | if (c >= ' ' && c !='@' && (c < 127 || unicode)) {
135 | writer.write(c);
136 | } else {
137 | writer.write("" + ((int) c) + ";");
138 | }
139 | }
140 | }
141 | }
142 |
143 | /*
144 | private final void writeIndent() throws IOException {
145 | writer.write("\r\n");
146 | for (int i = 0; i < depth; i++)
147 | writer.write(' ');
148 | }*/
149 |
150 | public void docdecl(String dd) throws IOException {
151 | writer.write("");
154 | }
155 |
156 | public void endDocument() throws IOException {
157 | while (depth > 0) {
158 | endTag(
159 | elementStack[depth * 3 - 3],
160 | elementStack[depth * 3 - 1]);
161 | }
162 | flush();
163 | }
164 |
165 | public void entityRef(String name) throws IOException {
166 | check(false);
167 | writer.write('&');
168 | writer.write(name);
169 | writer.write(';');
170 | }
171 |
172 | public boolean getFeature(String name) {
173 | //return false;
174 | return (
175 | "http://xmlpull.org/v1/doc/features.html#indent-output"
176 | .equals(
177 | name))
178 | ? indent[depth]
179 | : false;
180 | }
181 |
182 | public String getPrefix(String namespace, boolean create) {
183 | try {
184 | return getPrefix(namespace, false, create);
185 | }
186 | catch (IOException e) {
187 | throw new RuntimeException(e.toString());
188 | }
189 | }
190 |
191 | private final String getPrefix(
192 | String namespace,
193 | boolean includeDefault,
194 | boolean create)
195 | throws IOException {
196 |
197 | for (int i = nspCounts[depth + 1] * 2 - 2;
198 | i >= 0;
199 | i -= 2) {
200 | if (nspStack[i + 1].equals(namespace)
201 | && (includeDefault || !nspStack[i].equals(""))) {
202 | String cand = nspStack[i];
203 | for (int j = i + 2;
204 | j < nspCounts[depth + 1] * 2;
205 | j++) {
206 | if (nspStack[j].equals(cand)) {
207 | cand = null;
208 | break;
209 | }
210 | }
211 | if (cand != null)
212 | return cand;
213 | }
214 | }
215 |
216 | if (!create)
217 | return null;
218 |
219 | String prefix;
220 |
221 | if ("".equals(namespace))
222 | prefix = "";
223 | else {
224 | do {
225 | prefix = "n" + (auto++);
226 | for (int i = nspCounts[depth + 1] * 2 - 2;
227 | i >= 0;
228 | i -= 2) {
229 | if (prefix.equals(nspStack[i])) {
230 | prefix = null;
231 | break;
232 | }
233 | }
234 | }
235 | while (prefix == null);
236 | }
237 |
238 | boolean p = pending;
239 | pending = false;
240 | setPrefix(prefix, namespace);
241 | pending = p;
242 | return prefix;
243 | }
244 |
245 | public Object getProperty(String name) {
246 | throw new RuntimeException("Unsupported property");
247 | }
248 |
249 | public void ignorableWhitespace(String s)
250 | throws IOException {
251 | text(s);
252 | }
253 |
254 | public void setFeature(String name, boolean value) {
255 | if ("http://xmlpull.org/v1/doc/features.html#indent-output"
256 | .equals(name)) {
257 | indent[depth] = value;
258 | }
259 | else
260 | throw new RuntimeException("Unsupported Feature");
261 | }
262 |
263 | public void setProperty(String name, Object value) {
264 | throw new RuntimeException(
265 | "Unsupported Property:" + value);
266 | }
267 |
268 | public void setPrefix(String prefix, String namespace)
269 | throws IOException {
270 |
271 | check(false);
272 | if (prefix == null)
273 | prefix = "";
274 | if (namespace == null)
275 | namespace = "";
276 |
277 | String defined = getPrefix(namespace, true, false);
278 |
279 | // boil out if already defined
280 |
281 | if (prefix.equals(defined))
282 | return;
283 |
284 | int pos = (nspCounts[depth + 1]++) << 1;
285 |
286 | if (nspStack.length < pos + 1) {
287 | String[] hlp = new String[nspStack.length + 16];
288 | System.arraycopy(nspStack, 0, hlp, 0, pos);
289 | nspStack = hlp;
290 | }
291 |
292 | nspStack[pos++] = prefix;
293 | nspStack[pos] = namespace;
294 | }
295 |
296 | public void setOutput(Writer writer) {
297 | this.writer = writer;
298 |
299 | // elementStack = new String[12]; //nsp/prefix/name
300 | //nspCounts = new int[4];
301 | //nspStack = new String[8]; //prefix/nsp
302 | //indent = new boolean[4];
303 |
304 | nspCounts[0] = 2;
305 | nspCounts[1] = 2;
306 | nspStack[0] = "";
307 | nspStack[1] = "";
308 | nspStack[2] = "xml";
309 | nspStack[3] = "http://www.w3.org/XML/1998/namespace";
310 | pending = false;
311 | auto = 0;
312 | depth = 0;
313 |
314 | unicode = false;
315 | }
316 |
317 | public void setOutput(OutputStream os, String encoding)
318 | throws IOException {
319 | if (os == null)
320 | throw new IllegalArgumentException();
321 | setOutput(
322 | encoding == null
323 | ? new OutputStreamWriter(os)
324 | : new OutputStreamWriter(os, encoding));
325 | this.encoding = encoding;
326 | if (encoding != null
327 | && encoding.toLowerCase().startsWith("utf"))
328 | unicode = true;
329 | }
330 |
331 | public void startDocument(
332 | String encoding,
333 | Boolean standalone)
334 | throws IOException {
335 | writer.write("");
356 | }
357 |
358 | public XmlSerializer startTag(String namespace, String name)
359 | throws IOException {
360 | check(false);
361 |
362 | // if (namespace == null)
363 | // namespace = "";
364 |
365 | if (indent[depth]) {
366 | writer.write("\r\n");
367 | for (int i = 0; i < depth; i++)
368 | writer.write(" ");
369 | }
370 |
371 | int esp = depth * 3;
372 |
373 | if (elementStack.length < esp + 3) {
374 | String[] hlp = new String[elementStack.length + 12];
375 | System.arraycopy(elementStack, 0, hlp, 0, esp);
376 | elementStack = hlp;
377 | }
378 |
379 | String prefix =
380 | namespace == null
381 | ? ""
382 | : getPrefix(namespace, true, true);
383 |
384 | if ("".equals(namespace)) {
385 | for (int i = nspCounts[depth];
386 | i < nspCounts[depth + 1];
387 | i++) {
388 | if ("".equals(nspStack[i * 2]) && !"".equals(nspStack[i * 2 + 1])) {
389 | throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
390 | }
391 | }
392 | }
393 |
394 | elementStack[esp++] = namespace;
395 | elementStack[esp++] = prefix;
396 | elementStack[esp] = name;
397 |
398 | writer.write('<');
399 | if (!"".equals(prefix)) {
400 | writer.write(prefix);
401 | writer.write(':');
402 | }
403 |
404 | writer.write(name);
405 |
406 | pending = true;
407 |
408 | return this;
409 | }
410 |
411 | public XmlSerializer attribute(
412 | String namespace,
413 | String name,
414 | String value)
415 | throws IOException {
416 | if (!pending)
417 | throw new IllegalStateException("illegal position for attribute");
418 |
419 | // int cnt = nspCounts[depth];
420 |
421 | if (namespace == null)
422 | namespace = "";
423 |
424 | // depth--;
425 | // pending = false;
426 |
427 | String prefix =
428 | "".equals(namespace)
429 | ? ""
430 | : getPrefix(namespace, false, true);
431 |
432 | // pending = true;
433 | // depth++;
434 |
435 | /* if (cnt != nspCounts[depth]) {
436 | writer.write(' ');
437 | writer.write("xmlns");
438 | if (nspStack[cnt * 2] != null) {
439 | writer.write(':');
440 | writer.write(nspStack[cnt * 2]);
441 | }
442 | writer.write("=\"");
443 | writeEscaped(nspStack[cnt * 2 + 1], '"');
444 | writer.write('"');
445 | }
446 | */
447 |
448 | writer.write(' ');
449 | if (!"".equals(prefix)) {
450 | writer.write(prefix);
451 | writer.write(':');
452 | }
453 | writer.write(name);
454 | writer.write('=');
455 | char q = value.indexOf('"') == -1 ? '"' : '\'';
456 | writer.write(q);
457 | writeEscaped(value, q);
458 | writer.write(q);
459 |
460 | return this;
461 | }
462 |
463 | public void flush() throws IOException {
464 | check(false);
465 | writer.flush();
466 | }
467 | /*
468 | public void close() throws IOException {
469 | check();
470 | writer.close();
471 | }
472 | */
473 | public XmlSerializer endTag(String namespace, String name)
474 | throws IOException {
475 |
476 | if (!pending)
477 | depth--;
478 | // if (namespace == null)
479 | // namespace = "";
480 |
481 | if ((namespace == null
482 | && elementStack[depth * 3] != null)
483 | || (namespace != null
484 | && !namespace.equals(elementStack[depth * 3]))
485 | || !elementStack[depth * 3 + 2].equals(name))
486 | throw new IllegalArgumentException("{"+namespace+"}"+name+"> does not match start");
487 |
488 | if (pending) {
489 | check(true);
490 | depth--;
491 | }
492 | else {
493 | if (indent[depth + 1]) {
494 | writer.write("\r\n");
495 | for (int i = 0; i < depth; i++)
496 | writer.write(" ");
497 | }
498 |
499 | writer.write("");
500 | String prefix = elementStack[depth * 3 + 1];
501 | if (!"".equals(prefix)) {
502 | writer.write(prefix);
503 | writer.write(':');
504 | }
505 | writer.write(name);
506 | writer.write('>');
507 | }
508 |
509 | nspCounts[depth + 1] = nspCounts[depth];
510 | return this;
511 | }
512 |
513 | public String getNamespace() {
514 | return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3];
515 | }
516 |
517 | public String getName() {
518 | return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1];
519 | }
520 |
521 | public int getDepth() {
522 | return pending ? depth + 1 : depth;
523 | }
524 |
525 | public XmlSerializer text(String text) throws IOException {
526 | check(false);
527 | indent[depth] = false;
528 | writeEscaped(text, -1);
529 | return this;
530 | }
531 |
532 | public XmlSerializer text(char[] text, int start, int len)
533 | throws IOException {
534 | text(new String(text, start, len));
535 | return this;
536 | }
537 |
538 | public void cdsect(String data) throws IOException {
539 | check(false);
540 | writer.write("");
543 | }
544 |
545 | public void comment(String comment) throws IOException {
546 | check(false);
547 | writer.write("");
550 | }
551 |
552 | public void processingInstruction(String pi)
553 | throws IOException {
554 | check(false);
555 | writer.write("");
556 | writer.write(pi);
557 | writer.write("?>");
558 | }
559 | }
560 |
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/kdom/Document.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 |
22 | package org.kxml2.kdom;
23 |
24 | import java.io.*;
25 |
26 | import org.xmlpull.v1.*;
27 | /** The document consists of some legacy events and a single root
28 | element. This class basically adds some consistency checks to
29 | Node. */
30 |
31 | public class Document extends Node {
32 |
33 | protected int rootIndex = -1;
34 | String encoding;
35 | Boolean standalone;
36 |
37 | /** returns "#document" */
38 |
39 | public String getEncoding () {
40 | return encoding;
41 | }
42 |
43 | public void setEncoding(String enc) {
44 | this.encoding = enc;
45 | }
46 |
47 | public void setStandalone (Boolean standalone) {
48 | this.standalone = standalone;
49 | }
50 |
51 | public Boolean getStandalone() {
52 | return standalone;
53 | }
54 |
55 |
56 | public String getName() {
57 | return "#document";
58 | }
59 |
60 | /** Adds a child at the given index position. Throws
61 | an exception when a second root element is added */
62 |
63 | public void addChild(int index, int type, Object child) {
64 | if (type == ELEMENT) {
65 | // if (rootIndex != -1)
66 | // throw new RuntimeException("Only one document root element allowed");
67 |
68 | rootIndex = index;
69 | }
70 | else if (rootIndex >= index)
71 | rootIndex++;
72 |
73 | super.addChild(index, type, child);
74 | }
75 |
76 | /** reads the document and checks if the last event
77 | is END_DOCUMENT. If not, an exception is thrown.
78 | The end event is consumed. For parsing partial
79 | XML structures, consider using Node.parse (). */
80 |
81 | public void parse(XmlPullParser parser)
82 | throws IOException, XmlPullParserException {
83 |
84 | parser.require(XmlPullParser.START_DOCUMENT, null, null);
85 | parser.nextToken ();
86 |
87 | encoding = parser.getInputEncoding();
88 | standalone = (Boolean)parser.getProperty ("http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone");
89 |
90 | super.parse(parser);
91 |
92 | if (parser.getEventType() != XmlPullParser.END_DOCUMENT)
93 | throw new RuntimeException("Document end expected!");
94 |
95 | }
96 |
97 | public void removeChild(int index) {
98 | if (index == rootIndex)
99 | rootIndex = -1;
100 | else if (index < rootIndex)
101 | rootIndex--;
102 |
103 | super.removeChild(index);
104 | }
105 |
106 | /** returns the root element of this document. */
107 |
108 | public Element getRootElement() {
109 | if (rootIndex == -1)
110 | throw new RuntimeException("Document has no root element!");
111 |
112 | return (Element) getChild(rootIndex);
113 | }
114 |
115 |
116 | /** Writes this node to the given XmlWriter. For node and document,
117 | this method is identical to writeChildren, except that the
118 | stream is flushed automatically. */
119 |
120 | public void write(XmlSerializer writer)
121 | throws IOException {
122 |
123 | writer.startDocument(encoding, standalone);
124 | writeChildren(writer);
125 | writer.endDocument();
126 | }
127 |
128 |
129 | }
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/kdom/Element.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 | package org.kxml2.kdom;
22 |
23 | import java.io.*;
24 | import java.util.*;
25 |
26 | import org.xmlpull.v1.*;
27 |
28 | /**
29 | * In order to create an element, please use the createElement method
30 | * instead of invoking the constructor directly. The right place to
31 | * add user defined initialization code is the init method. */
32 |
33 | public class Element extends Node {
34 |
35 | protected String namespace;
36 | protected String name;
37 | protected Vector attributes;
38 | protected Node parent;
39 | protected Vector prefixes;
40 |
41 | public Element() {
42 | }
43 |
44 | /**
45 | * called when all properties are set, but before children
46 | * are parsed. Please do not use setParent for initialization
47 | * code any longer. */
48 |
49 | public void init() {
50 | }
51 |
52 |
53 |
54 |
55 | /**
56 | * removes all children and attributes */
57 |
58 | public void clear() {
59 | attributes = null;
60 | children = null;
61 | }
62 |
63 | /**
64 | * Forwards creation request to parent if any, otherwise
65 | * calls super.createElement. */
66 |
67 | public Element createElement(
68 | String namespace,
69 | String name) {
70 |
71 | return (this.parent == null)
72 | ? super.createElement(namespace, name)
73 | : this.parent.createElement(namespace, name);
74 | }
75 |
76 | /**
77 | * Returns the number of attributes of this element. */
78 |
79 | public int getAttributeCount() {
80 | return attributes == null ? 0 : attributes.size ();
81 | }
82 |
83 | public String getAttributeNamespace (int index) {
84 | return ((String []) attributes.elementAt (index)) [0];
85 | }
86 |
87 | /* public String getAttributePrefix (int index) {
88 | return ((String []) attributes.elementAt (index)) [1];
89 | }*/
90 |
91 | public String getAttributeName (int index) {
92 | return ((String []) attributes.elementAt (index)) [1];
93 | }
94 |
95 |
96 | public String getAttributeValue (int index) {
97 | return ((String []) attributes.elementAt (index)) [2];
98 | }
99 |
100 |
101 | public String getAttributeValue (String namespace, String name) {
102 | for (int i = 0; i < getAttributeCount (); i++) {
103 | if (name.equals (getAttributeName (i))
104 | && (namespace == null || namespace.equals (getAttributeNamespace(i)))) {
105 | return getAttributeValue (i);
106 | }
107 | }
108 | return null;
109 | }
110 |
111 | /**
112 | * Returns the root node, determined by ascending to the
113 | * all parents un of the root element. */
114 |
115 | public Node getRoot() {
116 |
117 | Element current = this;
118 |
119 | while (current.parent != null) {
120 | if (!(current.parent instanceof Element)) return current.parent;
121 | current = (Element) current.parent;
122 | }
123 |
124 | return current;
125 | }
126 |
127 | /**
128 | * returns the (local) name of the element */
129 |
130 | public String getName() {
131 | return name;
132 | }
133 |
134 | /**
135 | * returns the namespace of the element */
136 |
137 | public String getNamespace() {
138 | return namespace;
139 | }
140 |
141 |
142 | /**
143 | * returns the namespace for the given prefix */
144 |
145 | public String getNamespaceUri (String prefix) {
146 | int cnt = getNamespaceCount ();
147 | for (int i = 0; i < cnt; i++) {
148 | if (prefix == getNamespacePrefix (i) ||
149 | (prefix != null && prefix.equals (getNamespacePrefix (i))))
150 | return getNamespaceUri (i);
151 | }
152 | return parent instanceof Element ? ((Element) parent).getNamespaceUri (prefix) : null;
153 | }
154 |
155 |
156 | /**
157 | * returns the number of declared namespaces, NOT including
158 | * parent elements */
159 |
160 | public int getNamespaceCount () {
161 | return (prefixes == null ? 0 : prefixes.size ());
162 | }
163 |
164 |
165 | public String getNamespacePrefix (int i) {
166 | return ((String []) prefixes.elementAt (i)) [0];
167 | }
168 |
169 | public String getNamespaceUri (int i) {
170 | return ((String []) prefixes.elementAt (i)) [1];
171 | }
172 |
173 |
174 | /**
175 | * Returns the parent node of this element */
176 |
177 | public Node getParent() {
178 | return parent;
179 | }
180 |
181 | /*
182 | * Returns the parent element if available, null otherwise
183 |
184 | public Element getParentElement() {
185 | return (parent instanceof Element)
186 | ? ((Element) parent)
187 | : null;
188 | }
189 | */
190 |
191 | /**
192 | * Builds the child elements from the given Parser. By overwriting
193 | * parse, an element can take complete control over parsing its
194 | * subtree. */
195 |
196 | public void parse(XmlPullParser parser)
197 | throws IOException, XmlPullParserException {
198 |
199 | for (int i = parser.getNamespaceCount (parser.getDepth () - 1);
200 | i < parser.getNamespaceCount (parser.getDepth ()); i++) {
201 | setPrefix (parser.getNamespacePrefix (i), parser.getNamespaceUri(i));
202 | }
203 |
204 |
205 | for (int i = 0; i < parser.getAttributeCount (); i++)
206 | setAttribute (parser.getAttributeNamespace (i),
207 | // parser.getAttributePrefix (i),
208 | parser.getAttributeName (i),
209 | parser.getAttributeValue (i));
210 |
211 |
212 | // if (prefixMap == null) throw new RuntimeException ("!!");
213 |
214 | init();
215 |
216 |
217 | if (parser.isEmptyElementTag())
218 | parser.nextToken ();
219 | else {
220 | parser.nextToken ();
221 | super.parse(parser);
222 |
223 | if (getChildCount() == 0)
224 | addChild(IGNORABLE_WHITESPACE, "");
225 | }
226 |
227 | parser.require(
228 | XmlPullParser.END_TAG,
229 | getNamespace(),
230 | getName());
231 |
232 | parser.nextToken ();
233 | }
234 |
235 |
236 | /**
237 | * Sets the given attribute; a value of null removes the attribute */
238 |
239 | public void setAttribute (String namespace, String name, String value) {
240 | if (attributes == null)
241 | attributes = new Vector ();
242 |
243 | if (namespace == null)
244 | namespace = "";
245 |
246 | for (int i = attributes.size()-1; i >=0; i--){
247 | String[] attribut = (String[]) attributes.elementAt(i);
248 | if (attribut[0].equals(namespace) &&
249 | attribut[1].equals(name)){
250 |
251 | if (value == null) {
252 | attributes.removeElementAt(i);
253 | }
254 | else {
255 | attribut[2] = value;
256 | }
257 | return;
258 | }
259 | }
260 |
261 | attributes.addElement
262 | (new String [] {namespace, name, value});
263 | }
264 |
265 |
266 | /**
267 | * Sets the given prefix; a namespace value of null removess the
268 | * prefix */
269 |
270 | public void setPrefix (String prefix, String namespace) {
271 | if (prefixes == null) prefixes = new Vector ();
272 | prefixes.addElement (new String [] {prefix, namespace});
273 | }
274 |
275 |
276 | /**
277 | * sets the name of the element */
278 |
279 | public void setName(String name) {
280 | this.name = name;
281 | }
282 |
283 | /**
284 | * sets the namespace of the element. Please note: For no
285 | * namespace, please use Xml.NO_NAMESPACE, null is not a legal
286 | * value. Currently, null is converted to Xml.NO_NAMESPACE, but
287 | * future versions may throw an exception. */
288 |
289 | public void setNamespace(String namespace) {
290 | if (namespace == null)
291 | throw new NullPointerException ("Use \"\" for empty namespace");
292 | this.namespace = namespace;
293 | }
294 |
295 | /**
296 | * Sets the Parent of this element. Automatically called from the
297 | * add method. Please use with care, you can simply
298 | * create inconsitencies in the document tree structure using
299 | * this method! */
300 |
301 | protected void setParent(Node parent) {
302 | this.parent = parent;
303 | }
304 |
305 |
306 | /**
307 | * Writes this element and all children to the given XmlWriter. */
308 |
309 | public void write(XmlSerializer writer)
310 | throws IOException {
311 |
312 | if (prefixes != null) {
313 | for (int i = 0; i < prefixes.size (); i++) {
314 | writer.setPrefix (getNamespacePrefix (i), getNamespaceUri (i));
315 | }
316 | }
317 |
318 | writer.startTag(
319 | getNamespace(),
320 | getName());
321 |
322 | int len = getAttributeCount();
323 |
324 | for (int i = 0; i < len; i++) {
325 | writer.attribute(
326 | getAttributeNamespace(i),
327 | getAttributeName(i),
328 | getAttributeValue(i));
329 | }
330 |
331 | writeChildren(writer);
332 |
333 | writer.endTag(getNamespace (), getName ());
334 | }
335 | }
336 |
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/kdom/Node.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 | package org.kxml2.kdom;
22 |
23 | import java.util.*;
24 | import java.io.*;
25 | import org.xmlpull.v1.*;
26 | /** A common base class for Document and Element, also used for
27 | storing XML fragments. */
28 |
29 | public class Node { //implements XmlIO{
30 |
31 | public static final int DOCUMENT = 0;
32 | public static final int ELEMENT = 2;
33 | public static final int TEXT = 4;
34 | public static final int CDSECT = 5;
35 | public static final int ENTITY_REF = 6;
36 | public static final int IGNORABLE_WHITESPACE = 7;
37 | public static final int PROCESSING_INSTRUCTION = 8;
38 | public static final int COMMENT = 9;
39 | public static final int DOCDECL = 10;
40 |
41 | protected Vector children;
42 | protected StringBuffer types;
43 |
44 | /** inserts the given child object of the given type at the
45 | given index. */
46 |
47 | public void addChild(int index, int type, Object child) {
48 |
49 | if (child == null)
50 | throw new NullPointerException();
51 |
52 | if (children == null) {
53 | children = new Vector();
54 | types = new StringBuffer();
55 | }
56 |
57 | if (type == ELEMENT) {
58 | if (!(child instanceof Element))
59 | throw new RuntimeException("Element obj expected)");
60 |
61 | ((Element) child).setParent(this);
62 | }
63 | else if (!(child instanceof String))
64 | throw new RuntimeException("String expected");
65 |
66 | children.insertElementAt(child, index);
67 | types.insert(index, (char) type);
68 | }
69 |
70 | /** convenience method for addChild (getChildCount (), child) */
71 |
72 | public void addChild(int type, Object child) {
73 | addChild(getChildCount(), type, child);
74 | }
75 |
76 | /** Builds a default element with the given properties. Elements
77 | should always be created using this method instead of the
78 | constructor in order to enable construction of specialized
79 | subclasses by deriving custom Document classes. Please note:
80 | For no namespace, please use Xml.NO_NAMESPACE, null is not a
81 | legal value. Currently, null is converted to Xml.NO_NAMESPACE,
82 | but future versions may throw an exception. */
83 |
84 | public Element createElement(String namespace, String name) {
85 |
86 | Element e = new Element();
87 | e.namespace = namespace == null ? "" : namespace;
88 | e.name = name;
89 | return e;
90 | }
91 |
92 | /** Returns the child object at the given index. For child
93 | elements, an Element object is returned. For all other child
94 | types, a String is returned. */
95 |
96 | public Object getChild(int index) {
97 | return children.elementAt(index);
98 | }
99 |
100 | /** Returns the number of child objects */
101 |
102 | public int getChildCount() {
103 | return children == null ? 0 : children.size();
104 | }
105 |
106 | /** returns the element at the given index. If the node at the
107 | given index is a text node, null is returned */
108 |
109 | public Element getElement(int index) {
110 | Object child = getChild(index);
111 | return (child instanceof Element) ? (Element) child : null;
112 | }
113 |
114 | /** Returns the element with the given namespace and name. If the
115 | element is not found, or more than one matching elements are
116 | found, an exception is thrown. */
117 |
118 | public Element getElement(String namespace, String name) {
119 |
120 | int i = indexOf(namespace, name, 0);
121 | int j = indexOf(namespace, name, i + 1);
122 |
123 | if (i == -1 || j != -1)
124 | throw new RuntimeException(
125 | "Element {"
126 | + namespace
127 | + "}"
128 | + name
129 | + (i == -1 ? " not found in " : " more than once in ")
130 | + this);
131 |
132 | return getElement(i);
133 | }
134 |
135 | /* returns "#document-fragment". For elements, the element name is returned
136 |
137 | public String getName() {
138 | return "#document-fragment";
139 | }
140 |
141 | /** Returns the namespace of the current element. For Node
142 | and Document, Xml.NO_NAMESPACE is returned.
143 |
144 | public String getNamespace() {
145 | return "";
146 | }
147 |
148 | public int getNamespaceCount () {
149 | return 0;
150 | }
151 |
152 | /** returns the text content if the element has text-only
153 | content. Throws an exception for mixed content
154 |
155 | public String getText() {
156 |
157 | StringBuffer buf = new StringBuffer();
158 | int len = getChildCount();
159 |
160 | for (int i = 0; i < len; i++) {
161 | if (isText(i))
162 | buf.append(getText(i));
163 | else if (getType(i) == ELEMENT)
164 | throw new RuntimeException("not text-only content!");
165 | }
166 |
167 | return buf.toString();
168 | }
169 | */
170 |
171 | /** Returns the text node with the given index or null if the node
172 | with the given index is not a text node. */
173 |
174 | public String getText(int index) {
175 | return (isText(index)) ? (String) getChild(index) : null;
176 | }
177 |
178 | /** Returns the type of the child at the given index. Possible
179 | types are ELEMENT, TEXT, COMMENT, and PROCESSING_INSTRUCTION */
180 |
181 | public int getType(int index) {
182 | return types.charAt(index);
183 | }
184 |
185 | /** Convenience method for indexOf (getNamespace (), name,
186 | startIndex).
187 |
188 | public int indexOf(String name, int startIndex) {
189 | return indexOf(getNamespace(), name, startIndex);
190 | }
191 | */
192 |
193 | /** Performs search for an element with the given namespace and
194 | name, starting at the given start index. A null namespace
195 | matches any namespace, please use Xml.NO_NAMESPACE for no
196 | namespace). returns -1 if no matching element was found. */
197 |
198 | public int indexOf(String namespace, String name, int startIndex) {
199 |
200 | int len = getChildCount();
201 |
202 | for (int i = startIndex; i < len; i++) {
203 |
204 | Element child = getElement(i);
205 |
206 | if (child != null
207 | && name.equals(child.getName())
208 | && (namespace == null || namespace.equals(child.getNamespace())))
209 | return i;
210 | }
211 | return -1;
212 | }
213 |
214 | public boolean isText(int i) {
215 | int t = getType(i);
216 | return t == TEXT || t == IGNORABLE_WHITESPACE || t == CDSECT;
217 | }
218 |
219 | /** Recursively builds the child elements from the given parser
220 | until an end tag or end document is found.
221 | The end tag is not consumed. */
222 |
223 | public void parse(XmlPullParser parser)
224 | throws IOException, XmlPullParserException {
225 |
226 | boolean leave = false;
227 |
228 | do {
229 | int type = parser.getEventType();
230 |
231 | // System.out.println(parser.getPositionDescription());
232 |
233 | switch (type) {
234 |
235 | case XmlPullParser.START_TAG :
236 | {
237 | Element child =
238 | createElement(
239 | parser.getNamespace(),
240 | parser.getName());
241 | // child.setAttributes (event.getAttributes ());
242 | addChild(ELEMENT, child);
243 |
244 | // order is important here since
245 | // setparent may perform some init code!
246 |
247 | child.parse(parser);
248 | break;
249 | }
250 |
251 | case XmlPullParser.END_DOCUMENT :
252 | case XmlPullParser.END_TAG :
253 | leave = true;
254 | break;
255 |
256 | default :
257 | if (parser.getText() != null)
258 | addChild(
259 | type == XmlPullParser.ENTITY_REF ? TEXT : type,
260 | parser.getText());
261 | else if (
262 | type == XmlPullParser.ENTITY_REF
263 | && parser.getName() != null) {
264 | addChild(ENTITY_REF, parser.getName());
265 | }
266 | parser.nextToken();
267 | }
268 | }
269 | while (!leave);
270 | }
271 |
272 | /** Removes the child object at the given index */
273 |
274 | public void removeChild(int idx) {
275 | children.removeElementAt(idx);
276 |
277 | /*** Modification by HHS - start ***/
278 | // types.deleteCharAt (index);
279 | /***/
280 | int n = types.length() - 1;
281 |
282 | for (int i = idx; i < n; i++)
283 | types.setCharAt(i, types.charAt(i + 1));
284 |
285 | types.setLength(n);
286 |
287 | /*** Modification by HHS - end ***/
288 | }
289 |
290 | /* returns a valid XML representation of this Element including
291 | attributes and children.
292 | public String toString() {
293 | try {
294 | ByteArrayOutputStream bos =
295 | new ByteArrayOutputStream();
296 | XmlWriter xw =
297 | new XmlWriter(new OutputStreamWriter(bos));
298 | write(xw);
299 | xw.close();
300 | return new String(bos.toByteArray());
301 | }
302 | catch (IOException e) {
303 | throw new RuntimeException(e.toString());
304 | }
305 | }
306 | */
307 |
308 | /** Writes this node to the given XmlWriter. For node and document,
309 | this method is identical to writeChildren, except that the
310 | stream is flushed automatically. */
311 |
312 | public void write(XmlSerializer writer) throws IOException {
313 | writeChildren(writer);
314 | writer.flush();
315 | }
316 |
317 | /** Writes the children of this node to the given XmlWriter. */
318 |
319 | public void writeChildren(XmlSerializer writer) throws IOException {
320 | if (children == null)
321 | return;
322 |
323 | int len = children.size();
324 |
325 | for (int i = 0; i < len; i++) {
326 | int type = getType(i);
327 | Object child = children.elementAt(i);
328 | switch (type) {
329 | case ELEMENT :
330 | ((Element) child).write(writer);
331 | break;
332 |
333 | case TEXT :
334 | writer.text((String) child);
335 | break;
336 |
337 | case IGNORABLE_WHITESPACE :
338 | writer.ignorableWhitespace((String) child);
339 | break;
340 |
341 | case CDSECT :
342 | writer.cdsect((String) child);
343 | break;
344 |
345 | case COMMENT :
346 | writer.comment((String) child);
347 | break;
348 |
349 | case ENTITY_REF :
350 | writer.entityRef((String) child);
351 | break;
352 |
353 | case PROCESSING_INSTRUCTION :
354 | writer.processingInstruction((String) child);
355 | break;
356 |
357 | case DOCDECL :
358 | writer.docdecl((String) child);
359 | break;
360 |
361 | default :
362 | throw new RuntimeException("Illegal type: " + type);
363 | }
364 | }
365 | }
366 | }
367 |
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/wap/Wbxml.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 | package org.kxml2.wap;
22 |
23 |
24 | /** contains the WBXML constants */
25 |
26 |
27 | public interface Wbxml {
28 |
29 | static public final int SWITCH_PAGE = 0;
30 | static public final int END = 1;
31 | static public final int ENTITY = 2;
32 | static public final int STR_I = 3;
33 | static public final int LITERAL = 4;
34 | static public final int EXT_I_0 = 0x40;
35 | static public final int EXT_I_1 = 0x41;
36 | static public final int EXT_I_2 = 0x42;
37 | static public final int PI = 0x43;
38 | static public final int LITERAL_C = 0x44;
39 | static public final int EXT_T_0 = 0x80;
40 | static public final int EXT_T_1 = 0x81;
41 | static public final int EXT_T_2 = 0x82;
42 | static public final int STR_T = 0x83;
43 | static public final int LITERAL_A = 0x084;
44 | static public final int EXT_0 = 0x0c0;
45 | static public final int EXT_1 = 0x0c1;
46 | static public final int EXT_2 = 0x0c2;
47 | static public final int OPAQUE = 0x0c3;
48 | static public final int LITERAL_AC = 0x0c4;
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/wap/WbxmlParser.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2002,2003,2004 Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 | // Contributors: Bjorn Aadland, Chris Bartley, Nicola Fankhauser,
22 | // Victor Havin, Christian Kurzke, Bogdan Onoiu,
23 | // Elias Ross, Jain Sanjay, David Santoro.
24 |
25 | package org.kxml2.wap;
26 |
27 | import java.io.*;
28 | import java.util.Vector;
29 | import java.util.Hashtable;
30 |
31 | import org.xmlpull.v1.*;
32 |
33 |
34 | public class WbxmlParser implements XmlPullParser {
35 |
36 | static final String HEX_DIGITS = "0123456789abcdef";
37 |
38 | /** Parser event type for Wbxml-specific events. The Wbxml event code can be
39 | * accessed with getWapCode() */
40 |
41 | public static final int WAP_EXTENSION = 64;
42 |
43 | static final private String UNEXPECTED_EOF =
44 | "Unexpected EOF";
45 | static final private String ILLEGAL_TYPE =
46 | "Wrong event type";
47 |
48 | private InputStream in;
49 |
50 | private int TAG_TABLE = 0;
51 | private int ATTR_START_TABLE = 1;
52 | private int ATTR_VALUE_TABLE = 2;
53 |
54 | private String[] attrStartTable;
55 | private String[] attrValueTable;
56 | private String[] tagTable;
57 | private byte[] stringTable;
58 | private Hashtable cacheStringTable = null;
59 | private boolean processNsp;
60 |
61 | private int depth;
62 | private String[] elementStack = new String[16];
63 | private String[] nspStack = new String[8];
64 | private int[] nspCounts = new int[4];
65 |
66 | private int attributeCount;
67 | private String[] attributes = new String[16];
68 | private int nextId = -2;
69 |
70 | private Vector tables = new Vector();
71 |
72 | private int version;
73 | private int publicIdentifierId;
74 |
75 | // StartTag current;
76 | // ParseEvent next;
77 |
78 | private String prefix;
79 | private String namespace;
80 | private String name;
81 | private String text;
82 |
83 | private Object wapExtensionData;
84 | private int wapCode;
85 |
86 | private int type;
87 |
88 | private boolean degenerated;
89 | private boolean isWhitespace;
90 | private String encoding;
91 |
92 | public boolean getFeature(String feature) {
93 | if (XmlPullParser
94 | .FEATURE_PROCESS_NAMESPACES
95 | .equals(feature))
96 | return processNsp;
97 | else
98 | return false;
99 | }
100 |
101 | public String getInputEncoding() {
102 | return encoding;
103 | }
104 |
105 | public void defineEntityReplacementText(
106 | String entity,
107 | String value)
108 | throws XmlPullParserException {
109 |
110 | // just ignore, has no effect
111 | }
112 |
113 | public Object getProperty(String property) {
114 | return null;
115 | }
116 |
117 | public int getNamespaceCount(int depth) {
118 | if (depth > this.depth)
119 | throw new IndexOutOfBoundsException();
120 | return nspCounts[depth];
121 | }
122 |
123 | public String getNamespacePrefix(int pos) {
124 | return nspStack[pos << 1];
125 | }
126 |
127 | public String getNamespaceUri(int pos) {
128 | return nspStack[(pos << 1) + 1];
129 | }
130 |
131 | public String getNamespace(String prefix) {
132 |
133 | if ("xml".equals(prefix))
134 | return "http://www.w3.org/XML/1998/namespace";
135 | if ("xmlns".equals(prefix))
136 | return "http://www.w3.org/2000/xmlns/";
137 |
138 | for (int i = (getNamespaceCount(depth) << 1) - 2;
139 | i >= 0;
140 | i -= 2) {
141 | if (prefix == null) {
142 | if (nspStack[i] == null)
143 | return nspStack[i + 1];
144 | }
145 | else if (prefix.equals(nspStack[i]))
146 | return nspStack[i + 1];
147 | }
148 | return null;
149 | }
150 |
151 | public int getDepth() {
152 | return depth;
153 | }
154 |
155 | public String getPositionDescription() {
156 |
157 | StringBuffer buf =
158 | new StringBuffer(
159 | type < TYPES.length ? TYPES[type] : "unknown");
160 | buf.append(' ');
161 |
162 | if (type == START_TAG || type == END_TAG) {
163 | if (degenerated)
164 | buf.append("(empty) ");
165 | buf.append('<');
166 | if (type == END_TAG)
167 | buf.append('/');
168 |
169 | if (prefix != null)
170 | buf.append("{" + namespace + "}" + prefix + ":");
171 | buf.append(name);
172 |
173 | int cnt = attributeCount << 2;
174 | for (int i = 0; i < cnt; i += 4) {
175 | buf.append(' ');
176 | if (attributes[i + 1] != null)
177 | buf.append(
178 | "{"
179 | + attributes[i]
180 | + "}"
181 | + attributes[i
182 | + 1]
183 | + ":");
184 | buf.append(
185 | attributes[i
186 | + 2]
187 | + "='"
188 | + attributes[i
189 | + 3]
190 | + "'");
191 | }
192 |
193 | buf.append('>');
194 | }
195 | else if (type == IGNORABLE_WHITESPACE);
196 | else if (type != TEXT)
197 | buf.append(getText());
198 | else if (isWhitespace)
199 | buf.append("(whitespace)");
200 | else {
201 | String text = getText();
202 | if (text.length() > 16)
203 | text = text.substring(0, 16) + "...";
204 | buf.append(text);
205 | }
206 |
207 | return buf.toString();
208 | }
209 |
210 | public int getLineNumber() {
211 | return -1;
212 | }
213 |
214 | public int getColumnNumber() {
215 | return -1;
216 | }
217 |
218 | public boolean isWhitespace()
219 | throws XmlPullParserException {
220 | if (type != TEXT
221 | && type != IGNORABLE_WHITESPACE
222 | && type != CDSECT)
223 | exception(ILLEGAL_TYPE);
224 | return isWhitespace;
225 | }
226 |
227 | public String getText() {
228 | return text;
229 | }
230 |
231 | public char[] getTextCharacters(int[] poslen) {
232 | if (type >= TEXT) {
233 | poslen[0] = 0;
234 | poslen[1] = text.length();
235 | char[] buf = new char[text.length()];
236 | text.getChars(0, text.length(), buf, 0);
237 | return buf;
238 | }
239 |
240 | poslen[0] = -1;
241 | poslen[1] = -1;
242 | return null;
243 | }
244 |
245 | public String getNamespace() {
246 | return namespace;
247 | }
248 |
249 | public String getName() {
250 | return name;
251 | }
252 |
253 | public String getPrefix() {
254 | return prefix;
255 | }
256 |
257 | public boolean isEmptyElementTag()
258 | throws XmlPullParserException {
259 | if (type != START_TAG)
260 | exception(ILLEGAL_TYPE);
261 | return degenerated;
262 | }
263 |
264 | public int getAttributeCount() {
265 | return attributeCount;
266 | }
267 |
268 | public String getAttributeType(int index) {
269 | return "CDATA";
270 | }
271 |
272 | public boolean isAttributeDefault(int index) {
273 | return false;
274 | }
275 |
276 | public String getAttributeNamespace(int index) {
277 | if (index >= attributeCount)
278 | throw new IndexOutOfBoundsException();
279 | return attributes[index << 2];
280 | }
281 |
282 | public String getAttributeName(int index) {
283 | if (index >= attributeCount)
284 | throw new IndexOutOfBoundsException();
285 | return attributes[(index << 2) + 2];
286 | }
287 |
288 | public String getAttributePrefix(int index) {
289 | if (index >= attributeCount)
290 | throw new IndexOutOfBoundsException();
291 | return attributes[(index << 2) + 1];
292 | }
293 |
294 | public String getAttributeValue(int index) {
295 | if (index >= attributeCount)
296 | throw new IndexOutOfBoundsException();
297 | return attributes[(index << 2) + 3];
298 | }
299 |
300 | public String getAttributeValue(
301 | String namespace,
302 | String name) {
303 |
304 | for (int i = (attributeCount << 2) - 4;
305 | i >= 0;
306 | i -= 4) {
307 | if (attributes[i + 2].equals(name)
308 | && (namespace == null
309 | || attributes[i].equals(namespace)))
310 | return attributes[i + 3];
311 | }
312 |
313 | return null;
314 | }
315 |
316 | public int getEventType() throws XmlPullParserException {
317 | return type;
318 | }
319 |
320 |
321 | // TODO: Reuse resolveWapExtension here? Raw Wap extensions would still be accessible
322 | // via nextToken(); ....?
323 |
324 | public int next() throws XmlPullParserException, IOException {
325 |
326 | isWhitespace = true;
327 | int minType = 9999;
328 |
329 | while (true) {
330 |
331 | String save = text;
332 |
333 | nextImpl();
334 |
335 | if (type < minType)
336 | minType = type;
337 |
338 | if (minType > CDSECT) continue; // no "real" event so far
339 |
340 | if (minType >= TEXT) { // text, see if accumulate
341 |
342 | if (save != null) text = text == null ? save : save + text;
343 |
344 | switch(peekId()) {
345 | case Wbxml.ENTITY:
346 | case Wbxml.STR_I:
347 | case Wbxml.STR_T:
348 | case Wbxml.LITERAL:
349 | case Wbxml.LITERAL_C:
350 | case Wbxml.LITERAL_A:
351 | case Wbxml.LITERAL_AC: continue;
352 | }
353 | }
354 |
355 | break;
356 | }
357 |
358 | type = minType;
359 |
360 | if (type > TEXT)
361 | type = TEXT;
362 |
363 | return type;
364 | }
365 |
366 |
367 | public int nextToken() throws XmlPullParserException, IOException {
368 |
369 | isWhitespace = true;
370 | nextImpl();
371 | return type;
372 | }
373 |
374 |
375 |
376 | public int nextTag() throws XmlPullParserException, IOException {
377 |
378 | next();
379 | if (type == TEXT && isWhitespace)
380 | next();
381 |
382 | if (type != END_TAG && type != START_TAG)
383 | exception("unexpected type");
384 |
385 | return type;
386 | }
387 |
388 |
389 | public String nextText() throws XmlPullParserException, IOException {
390 | if (type != START_TAG)
391 | exception("precondition: START_TAG");
392 |
393 | next();
394 |
395 | String result;
396 |
397 | if (type == TEXT) {
398 | result = getText();
399 | next();
400 | }
401 | else
402 | result = "";
403 |
404 | if (type != END_TAG)
405 | exception("END_TAG expected");
406 |
407 | return result;
408 | }
409 |
410 |
411 | public void require(int type, String namespace, String name)
412 | throws XmlPullParserException, IOException {
413 |
414 | if (type != this.type
415 | || (namespace != null && !namespace.equals(getNamespace()))
416 | || (name != null && !name.equals(getName())))
417 | exception(
418 | "expected: " + (type == WAP_EXTENSION ? "WAP Ext." : (TYPES[type] + " {" + namespace + "}" + name)));
419 | }
420 |
421 |
422 | public void setInput(Reader reader) throws XmlPullParserException {
423 | exception("InputStream required");
424 | }
425 |
426 | public void setInput(InputStream in, String enc)
427 | throws XmlPullParserException {
428 |
429 | this.in = in;
430 |
431 | try {
432 | version = readByte();
433 | publicIdentifierId = readInt();
434 |
435 | if (publicIdentifierId == 0)
436 | readInt();
437 |
438 | int charset = readInt(); // skip charset
439 |
440 | if (null == enc){
441 | switch (charset){
442 | case 4: encoding = "ISO-8859-1"; break;
443 | case 106: encoding = "UTF-8"; break;
444 | // add more if you need them
445 | // http://www.iana.org/assignments/character-sets
446 | // case MIBenum: encoding = Name break;
447 | default: throw new UnsupportedEncodingException(""+charset);
448 | }
449 | }else{
450 | encoding = enc;
451 | }
452 |
453 | int strTabSize = readInt();
454 | stringTable = new byte[strTabSize];
455 |
456 | int ok = 0;
457 | while(ok < strTabSize){
458 | int cnt = in.read(stringTable, ok, strTabSize - ok);
459 | if(cnt <= 0) break;
460 | ok += cnt;
461 | }
462 |
463 | selectPage(0, true);
464 | selectPage(0, false);
465 | }
466 | catch (IOException e) {
467 | exception("Illegal input format");
468 | }
469 | }
470 |
471 | public void setFeature(String feature, boolean value)
472 | throws XmlPullParserException {
473 | if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature))
474 | processNsp = value;
475 | else
476 | exception("unsupported feature: " + feature);
477 | }
478 |
479 | public void setProperty(String property, Object value)
480 | throws XmlPullParserException {
481 | throw new XmlPullParserException("unsupported property: " + property);
482 | }
483 |
484 | // ---------------------- private / internal methods
485 |
486 | private final boolean adjustNsp()
487 | throws XmlPullParserException {
488 |
489 | boolean any = false;
490 |
491 | for (int i = 0; i < attributeCount << 2; i += 4) {
492 | // * 4 - 4; i >= 0; i -= 4) {
493 |
494 | String attrName = attributes[i + 2];
495 | int cut = attrName.indexOf(':');
496 | String prefix;
497 |
498 | if (cut != -1) {
499 | prefix = attrName.substring(0, cut);
500 | attrName = attrName.substring(cut + 1);
501 | }
502 | else if (attrName.equals("xmlns")) {
503 | prefix = attrName;
504 | attrName = null;
505 | }
506 | else
507 | continue;
508 |
509 | if (!prefix.equals("xmlns")) {
510 | any = true;
511 | }
512 | else {
513 | int j = (nspCounts[depth]++) << 1;
514 |
515 | nspStack = ensureCapacity(nspStack, j + 2);
516 | nspStack[j] = attrName;
517 | nspStack[j + 1] = attributes[i + 3];
518 |
519 | if (attrName != null
520 | && attributes[i + 3].equals(""))
521 | exception("illegal empty namespace");
522 |
523 | // prefixMap = new PrefixMap (prefixMap, attrName, attr.getValue ());
524 |
525 | //System.out.println (prefixMap);
526 |
527 | System.arraycopy(
528 | attributes,
529 | i + 4,
530 | attributes,
531 | i,
532 | ((--attributeCount) << 2) - i);
533 |
534 | i -= 4;
535 | }
536 | }
537 |
538 | if (any) {
539 | for (int i = (attributeCount << 2) - 4;
540 | i >= 0;
541 | i -= 4) {
542 |
543 | String attrName = attributes[i + 2];
544 | int cut = attrName.indexOf(':');
545 |
546 | if (cut == 0)
547 | throw new RuntimeException(
548 | "illegal attribute name: "
549 | + attrName
550 | + " at "
551 | + this);
552 |
553 | else if (cut != -1) {
554 | String attrPrefix =
555 | attrName.substring(0, cut);
556 |
557 | attrName = attrName.substring(cut + 1);
558 |
559 | String attrNs = getNamespace(attrPrefix);
560 |
561 | if (attrNs == null)
562 | throw new RuntimeException(
563 | "Undefined Prefix: "
564 | + attrPrefix
565 | + " in "
566 | + this);
567 |
568 | attributes[i] = attrNs;
569 | attributes[i + 1] = attrPrefix;
570 | attributes[i + 2] = attrName;
571 |
572 | for (int j = (attributeCount << 2) - 4;
573 | j > i;
574 | j -= 4)
575 | if (attrName.equals(attributes[j + 2])
576 | && attrNs.equals(attributes[j]))
577 | exception(
578 | "Duplicate Attribute: {"
579 | + attrNs
580 | + "}"
581 | + attrName);
582 | }
583 | }
584 | }
585 |
586 | int cut = name.indexOf(':');
587 |
588 | if (cut == 0)
589 | exception("illegal tag name: " + name);
590 | else if (cut != -1) {
591 | prefix = name.substring(0, cut);
592 | name = name.substring(cut + 1);
593 | }
594 |
595 | this.namespace = getNamespace(prefix);
596 |
597 | if (this.namespace == null) {
598 | if (prefix != null)
599 | exception("undefined prefix: " + prefix);
600 | this.namespace = NO_NAMESPACE;
601 | }
602 |
603 | return any;
604 | }
605 |
606 | private final void setTable(int page, int type, String[] table) {
607 | if(stringTable != null){
608 | throw new RuntimeException("setXxxTable must be called before setInput!");
609 | }
610 | while(tables.size() < 3*page +3){
611 | tables.addElement(null);
612 | }
613 | tables.setElementAt(table, page*3+type);
614 | }
615 |
616 |
617 |
618 |
619 |
620 | private final void exception(String desc)
621 | throws XmlPullParserException {
622 | throw new XmlPullParserException(desc, this, null);
623 | }
624 |
625 |
626 | private void selectPage(int nr, boolean tags) throws XmlPullParserException{
627 | if(tables.size() == 0 && nr == 0) return;
628 |
629 | if(nr*3 > tables.size())
630 | exception("Code Page "+nr+" undefined!");
631 |
632 | if(tags)
633 | tagTable = (String[]) tables.elementAt(nr * 3 + TAG_TABLE);
634 | else {
635 | attrStartTable = (String[]) tables.elementAt(nr * 3 + ATTR_START_TABLE);
636 | attrValueTable = (String[]) tables.elementAt(nr * 3 + ATTR_VALUE_TABLE);
637 | }
638 | }
639 |
640 | private final void nextImpl()
641 | throws IOException, XmlPullParserException {
642 |
643 | String s;
644 |
645 | if (type == END_TAG) {
646 | depth--;
647 | }
648 |
649 | if (degenerated) {
650 | type = XmlPullParser.END_TAG;
651 | degenerated = false;
652 | return;
653 | }
654 |
655 | text = null;
656 | prefix = null;
657 | name = null;
658 |
659 | int id = peekId ();
660 | while(id == Wbxml.SWITCH_PAGE){
661 | nextId = -2;
662 | selectPage(readByte(), true);
663 | id = peekId();
664 | }
665 | nextId = -2;
666 |
667 | switch (id) {
668 | case -1 :
669 | type = XmlPullParser.END_DOCUMENT;
670 | break;
671 |
672 | case Wbxml.END :
673 | {
674 | int sp = (depth - 1) << 2;
675 |
676 | type = END_TAG;
677 | namespace = elementStack[sp];
678 | prefix = elementStack[sp + 1];
679 | name = elementStack[sp + 2];
680 | }
681 | break;
682 |
683 | case Wbxml.ENTITY :
684 | {
685 | type = ENTITY_REF;
686 | char c = (char) readInt();
687 | text = "" + c;
688 | name = "#" + ((int) c);
689 | }
690 |
691 | break;
692 |
693 | case Wbxml.STR_I :
694 | type = TEXT;
695 | text = readStrI();
696 | break;
697 |
698 | case Wbxml.EXT_I_0 :
699 | case Wbxml.EXT_I_1 :
700 | case Wbxml.EXT_I_2 :
701 | case Wbxml.EXT_T_0 :
702 | case Wbxml.EXT_T_1 :
703 | case Wbxml.EXT_T_2 :
704 | case Wbxml.EXT_0 :
705 | case Wbxml.EXT_1 :
706 | case Wbxml.EXT_2 :
707 | case Wbxml.OPAQUE :
708 |
709 | type = WAP_EXTENSION;
710 | wapCode = id;
711 | wapExtensionData = parseWapExtension(id);
712 | break;
713 |
714 | case Wbxml.PI :
715 | throw new RuntimeException("PI curr. not supp.");
716 | // readPI;
717 | // break;
718 |
719 | case Wbxml.STR_T :
720 | {
721 | type = TEXT;
722 | text = readStrT();
723 | }
724 | break;
725 |
726 | default :
727 | parseElement(id);
728 | }
729 | // }
730 | // while (next == null);
731 |
732 | // return next;
733 | }
734 |
735 | /** Overwrite this method to intercept all wap events */
736 |
737 | public Object parseWapExtension(int id) throws IOException, XmlPullParserException {
738 |
739 | switch (id) {
740 | case Wbxml.EXT_I_0 :
741 | case Wbxml.EXT_I_1 :
742 | case Wbxml.EXT_I_2 :
743 | return readStrI();
744 |
745 | case Wbxml.EXT_T_0 :
746 | case Wbxml.EXT_T_1 :
747 | case Wbxml.EXT_T_2 :
748 | return new Integer(readInt());
749 |
750 | case Wbxml.EXT_0 :
751 | case Wbxml.EXT_1 :
752 | case Wbxml.EXT_2 :
753 | return null;
754 |
755 | case Wbxml.OPAQUE :
756 | {
757 | int count = readInt();
758 | byte[] buf = new byte[count];
759 |
760 | while(count > 0){
761 | count -= in.read(buf, buf.length-count, count);
762 | }
763 |
764 | return buf;
765 | } // case OPAQUE
766 |
767 |
768 | default:
769 | exception("illegal id: "+id);
770 | return null; // dead code
771 | } // SWITCH
772 | }
773 |
774 | public void readAttr() throws IOException, XmlPullParserException {
775 |
776 | int id = readByte();
777 | int i = 0;
778 |
779 | while (id != 1) {
780 |
781 | while(id == Wbxml.SWITCH_PAGE){
782 | selectPage(readByte(), false);
783 | id = readByte();
784 | }
785 |
786 | String name = resolveId(attrStartTable, id);
787 | StringBuffer value;
788 |
789 | int cut = name.indexOf('=');
790 |
791 | if (cut == -1)
792 | value = new StringBuffer();
793 | else {
794 | value =
795 | new StringBuffer(name.substring(cut + 1));
796 | name = name.substring(0, cut);
797 | }
798 |
799 | id = readByte();
800 | while (id > 128
801 | || id == Wbxml.SWITCH_PAGE
802 | || id == Wbxml.ENTITY
803 | || id == Wbxml.STR_I
804 | || id == Wbxml.STR_T
805 | || (id >= Wbxml.EXT_I_0 && id <= Wbxml.EXT_I_2)
806 | || (id >= Wbxml.EXT_T_0 && id <= Wbxml.EXT_T_2)) {
807 |
808 | switch (id) {
809 | case Wbxml.SWITCH_PAGE :
810 | selectPage(readByte(), false);
811 | break;
812 |
813 | case Wbxml.ENTITY :
814 | value.append((char) readInt());
815 | break;
816 |
817 | case Wbxml.STR_I :
818 | value.append(readStrI());
819 | break;
820 |
821 | case Wbxml.EXT_I_0 :
822 | case Wbxml.EXT_I_1 :
823 | case Wbxml.EXT_I_2 :
824 | case Wbxml.EXT_T_0 :
825 | case Wbxml.EXT_T_1 :
826 | case Wbxml.EXT_T_2 :
827 | case Wbxml.EXT_0 :
828 | case Wbxml.EXT_1 :
829 | case Wbxml.EXT_2 :
830 | case Wbxml.OPAQUE :
831 | value.append(resolveWapExtension(id, parseWapExtension(id)));
832 | break;
833 |
834 | case Wbxml.STR_T :
835 | value.append(readStrT());
836 | break;
837 |
838 | default :
839 | value.append(
840 | resolveId(attrValueTable, id));
841 | }
842 |
843 | id = readByte();
844 | }
845 |
846 | attributes = ensureCapacity(attributes, i + 4);
847 |
848 | attributes[i++] = "";
849 | attributes[i++] = null;
850 | attributes[i++] = name;
851 | attributes[i++] = value.toString();
852 |
853 | attributeCount++;
854 | }
855 | }
856 |
857 | private int peekId () throws IOException {
858 | if (nextId == -2) {
859 | nextId = in.read ();
860 | }
861 | return nextId;
862 | }
863 |
864 | /** overwrite for own WAP extension handling in attributes and high level parsing
865 | * (above nextToken() level) */
866 |
867 | protected String resolveWapExtension(int id, Object data){
868 |
869 | if(data instanceof byte[]){
870 | StringBuffer sb = new StringBuffer();
871 | byte[] b = (byte[]) data;
872 |
873 | for (int i = 0; i < b.length; i++) {
874 | sb.append(HEX_DIGITS.charAt((b[i] >> 4) & 0x0f));
875 | sb.append(HEX_DIGITS.charAt(b[i] & 0x0f));
876 | }
877 | return sb.toString();
878 | }
879 |
880 | return "$("+data+")";
881 | }
882 |
883 | String resolveId(String[] tab, int id) throws IOException {
884 | int idx = (id & 0x07f) - 5;
885 | if (idx == -1){
886 | wapCode = -1;
887 | return readStrT();
888 | }
889 | if (idx < 0
890 | || tab == null
891 | || idx >= tab.length
892 | || tab[idx] == null)
893 | throw new IOException("id " + id + " undef.");
894 |
895 | wapCode = idx+5;
896 |
897 | return tab[idx];
898 | }
899 |
900 | void parseElement(int id)
901 | throws IOException, XmlPullParserException {
902 |
903 | type = START_TAG;
904 | name = resolveId(tagTable, id & 0x03f);
905 |
906 | attributeCount = 0;
907 | if ((id & 128) != 0) {
908 | readAttr();
909 | }
910 |
911 | degenerated = (id & 64) == 0;
912 |
913 | int sp = depth++ << 2;
914 |
915 | // transfer to element stack
916 |
917 | elementStack = ensureCapacity(elementStack, sp + 4);
918 | elementStack[sp + 3] = name;
919 |
920 | if (depth >= nspCounts.length) {
921 | int[] bigger = new int[depth + 4];
922 | System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length);
923 | nspCounts = bigger;
924 | }
925 |
926 | nspCounts[depth] = nspCounts[depth - 1];
927 |
928 | for (int i = attributeCount - 1; i > 0; i--) {
929 | for (int j = 0; j < i; j++) {
930 | if (getAttributeName(i)
931 | .equals(getAttributeName(j)))
932 | exception(
933 | "Duplicate Attribute: "
934 | + getAttributeName(i));
935 | }
936 | }
937 |
938 | if (processNsp)
939 | adjustNsp();
940 | else
941 | namespace = "";
942 |
943 | elementStack[sp] = namespace;
944 | elementStack[sp + 1] = prefix;
945 | elementStack[sp + 2] = name;
946 |
947 | }
948 |
949 | private final String[] ensureCapacity(
950 | String[] arr,
951 | int required) {
952 | if (arr.length >= required)
953 | return arr;
954 | String[] bigger = new String[required + 16];
955 | System.arraycopy(arr, 0, bigger, 0, arr.length);
956 | return bigger;
957 | }
958 |
959 | int readByte() throws IOException {
960 | int i = in.read();
961 | if (i == -1)
962 | throw new IOException("Unexpected EOF");
963 | return i;
964 | }
965 |
966 | int readInt() throws IOException {
967 | int result = 0;
968 | int i;
969 |
970 | do {
971 | i = readByte();
972 | result = (result << 7) | (i & 0x7f);
973 | }
974 | while ((i & 0x80) != 0);
975 |
976 | return result;
977 | }
978 |
979 | String readStrI() throws IOException {
980 | ByteArrayOutputStream buf = new ByteArrayOutputStream();
981 | boolean wsp = true;
982 | while (true){
983 | int i = in.read();
984 | if (i == 0){
985 | break;
986 | }
987 | if (i == -1){
988 | throw new IOException(UNEXPECTED_EOF);
989 | }
990 | if (i > 32){
991 | wsp = false;
992 | }
993 | buf.write(i);
994 | }
995 | isWhitespace = wsp;
996 | String result = new String(buf.toByteArray(), encoding);
997 | buf.close();
998 | return result;
999 | }
1000 |
1001 | String readStrT() throws IOException {
1002 | int pos = readInt();
1003 | // As the main reason of stringTable is compression we build a cache of Strings
1004 | // stringTable is supposed to help create Strings from parts which means some cache hit rate
1005 | // This will help to minimize the Strings created when invoking readStrT() repeatedly
1006 | if (cacheStringTable == null){
1007 | //Lazy init if device is not using StringTable but inline 0x03 strings
1008 | cacheStringTable = new Hashtable();
1009 | }
1010 | String forReturn = (String) cacheStringTable.get(new Integer(pos));
1011 | if (forReturn == null){
1012 |
1013 | int end = pos;
1014 | while(end < stringTable.length && stringTable[end] != '\0'){
1015 | end++;
1016 | }
1017 | forReturn = new String(stringTable, pos, end-pos, encoding);
1018 | cacheStringTable.put(new Integer(pos), forReturn);
1019 | }
1020 | return forReturn;
1021 | }
1022 |
1023 | /**
1024 | * Sets the tag table for a given page.
1025 | * The first string in the array defines tag 5, the second tag 6 etc.
1026 | */
1027 |
1028 | public void setTagTable(int page, String[] table) {
1029 | setTable(page, TAG_TABLE, table);
1030 |
1031 | // this.tagTable = tagTable;
1032 | // if (page != 0)
1033 | // throw new RuntimeException("code pages curr. not supp.");
1034 | }
1035 |
1036 | /** Sets the attribute start Table for a given page.
1037 | * The first string in the array defines attribute
1038 | * 5, the second attribute 6 etc. Please use the
1039 | * character '=' (without quote!) as delimiter
1040 | * between the attribute name and the (start of the) value
1041 | */
1042 |
1043 | public void setAttrStartTable(
1044 | int page,
1045 | String[] table) {
1046 |
1047 | setTable(page, ATTR_START_TABLE, table);
1048 | }
1049 |
1050 | /** Sets the attribute value Table for a given page.
1051 | * The first string in the array defines attribute value 0x85,
1052 | * the second attribute value 0x86 etc.
1053 | */
1054 |
1055 | public void setAttrValueTable(
1056 | int page,
1057 | String[] table) {
1058 |
1059 | setTable(page, ATTR_VALUE_TABLE, table);
1060 | }
1061 |
1062 | /** Returns the token ID for start tags or the event type for wap proprietary events
1063 | * such as OPAQUE.
1064 | */
1065 |
1066 | public int getWapCode(){
1067 | return wapCode;
1068 | }
1069 |
1070 | public Object getWapExtensionData(){
1071 | return wapExtensionData;
1072 | }
1073 |
1074 |
1075 | }
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/wap/WbxmlSerializer.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 | //Contributors: Jonathan Cox, Bogdan Onoiu, Jerry Tian
22 |
23 | package org.kxml2.wap;
24 |
25 | import java.io.*;
26 | import java.util.*;
27 |
28 | import org.xmlpull.v1.*;
29 |
30 | // TODO: make some of the "direct" WBXML token writing methods public??
31 |
32 | /**
33 | * A class for writing WBXML. Does not support namespaces yet.
34 | */
35 | public class WbxmlSerializer implements XmlSerializer {
36 |
37 |
38 | Hashtable stringTable = new Hashtable();
39 |
40 | OutputStream out;
41 |
42 | ByteArrayOutputStream buf = new ByteArrayOutputStream();
43 | ByteArrayOutputStream stringTableBuf = new ByteArrayOutputStream();
44 |
45 | String pending;
46 | int depth;
47 | String name;
48 | String namespace;
49 | Vector attributes = new Vector();
50 |
51 | Hashtable attrStartTable = new Hashtable();
52 | Hashtable attrValueTable = new Hashtable();
53 | Hashtable tagTable = new Hashtable();
54 |
55 | private int attrPage;
56 | private int tagPage;
57 |
58 | private String encoding;
59 |
60 | private boolean headerSent = false;
61 |
62 | /**
63 | * Write an attribute.
64 | * Calls to attribute() MUST follow a call to startTag() immediately.
65 | * If there is no prefix defined for the given namespace,
66 | * a prefix will be defined automatically.
67 | */
68 | public XmlSerializer attribute(String namespace, String name, String value) {
69 | attributes.addElement(name);
70 | attributes.addElement(value);
71 | return this;
72 | }
73 |
74 |
75 | public void cdsect (String cdsect) throws IOException{
76 | text (cdsect);
77 | }
78 |
79 | /**
80 | * Add comment. Ignore for WBXML.
81 | */
82 | public void comment (String comment) {
83 | // silently ignore comment
84 | }
85 |
86 | /**
87 | * Docdecl isn't supported for WBXML.
88 | */
89 | public void docdecl (String docdecl) {
90 | throw new RuntimeException ("Cannot write docdecl for WBXML");
91 | }
92 |
93 | /**
94 | * EntityReference not supported for WBXML.
95 | */
96 | public void entityRef (String er) {
97 | throw new RuntimeException ("EntityReference not supported for WBXML");
98 | }
99 |
100 | /**
101 | * Return current tag depth.
102 | */
103 | public int getDepth() {
104 | return depth;
105 | }
106 |
107 | /**
108 | * Return the current value of the feature with given name.
109 | */
110 | public boolean getFeature (String name) {
111 | return false;
112 | }
113 |
114 | /**
115 | * Returns the namespace URI of the current element as set by startTag().
116 | * Namespaces is not yet implemented.
117 | */
118 | public String getNamespace() {
119 | // Namespaces is not yet implemented. So only null can be setted
120 | return null;
121 | }
122 |
123 | /**
124 | * Returns the name of the current element as set by startTag().
125 | * It can only be null before first call to startTag() or when last endTag()
126 | * is called to close first startTag().
127 | */
128 | public String getName() {
129 | return pending;
130 | }
131 |
132 | /**
133 | * Prefix for namespace not supported for WBXML. Not yet implemented.
134 | */
135 | public String getPrefix(String nsp, boolean create) {
136 | throw new RuntimeException ("NYI");
137 | }
138 |
139 | /**
140 | * Look up the value of a property.
141 | * @param name The name of property. Name is any fully-qualified URI.
142 | * @return The value of named property.
143 | */
144 | public Object getProperty (String name) {
145 | return null;
146 | }
147 |
148 | public void ignorableWhitespace (String sp) {
149 | }
150 |
151 | /**
152 | * Finish writing.
153 | * All unclosed start tags will be closed and output will be flushed.
154 | * After calling this method no more output can be serialized until
155 | * next call to setOutput().
156 | */
157 | public void endDocument() throws IOException {
158 | flush();
159 | }
160 |
161 | /**
162 | * Write all pending output to the stream.
163 | * After first call string table willn't be used and you can't add tag
164 | * which is not in tag table.
165 | */
166 | public void flush() throws IOException {
167 | checkPending(false);
168 |
169 | if (!headerSent) {
170 | writeInt(out, stringTableBuf.size());
171 | out.write(stringTableBuf.toByteArray());
172 | headerSent = true;
173 | }
174 |
175 | out.write(buf.toByteArray());
176 | buf.reset();
177 | }
178 |
179 | public void checkPending(boolean degenerated) throws IOException {
180 | if (pending == null)
181 | return;
182 |
183 | int len = attributes.size();
184 |
185 | int[] idx = (int[]) tagTable.get(pending);
186 |
187 | // if no entry in known table, then add as literal
188 | if (idx == null) {
189 | buf.write(len == 0
190 | ? (degenerated ? Wbxml.LITERAL : Wbxml.LITERAL_C)
191 | : (degenerated ? Wbxml.LITERAL_A : Wbxml.LITERAL_AC));
192 |
193 | writeStrT(pending, false);
194 | } else {
195 | if(idx[0] != tagPage){
196 | tagPage=idx[0];
197 | buf.write(Wbxml.SWITCH_PAGE);
198 | buf.write(tagPage);
199 | }
200 | buf.write(len == 0
201 | ? (degenerated ? idx[1] : idx[1] | 64)
202 | : (degenerated ? idx[1] | 128 : idx[1] | 192));
203 | }
204 |
205 | for (int i = 0; i < len;) {
206 | idx = (int[]) attrStartTable.get(attributes.elementAt(i));
207 |
208 | if (idx == null) {
209 | buf.write(Wbxml.LITERAL);
210 | writeStrT((String) attributes.elementAt(i), false);
211 | }
212 | else {
213 | if(idx[0] != attrPage){
214 | attrPage = idx[0];
215 | buf.write(0);
216 | buf.write(attrPage);
217 | }
218 | buf.write(idx[1]);
219 | }
220 | idx = (int[]) attrValueTable.get(attributes.elementAt(++i));
221 | if (idx == null) {
222 | writeStr((String) attributes.elementAt(i));
223 | }
224 | else {
225 | if(idx[0] != attrPage){
226 | attrPage = idx[0];
227 | buf.write(0);
228 | buf.write(attrPage);
229 | }
230 | buf.write(idx[1]);
231 | }
232 | ++i;
233 | }
234 |
235 | if (len > 0)
236 | buf.write(Wbxml.END);
237 |
238 | pending = null;
239 | attributes.removeAllElements();
240 | }
241 |
242 | /**
243 | * Not Yet Implemented.
244 | */
245 | public void processingInstruction(String pi) {
246 | throw new RuntimeException ("PI NYI");
247 | }
248 |
249 | /**
250 | * Set feature identified by name. There are no supported functions.
251 | */
252 | public void setFeature(String name, boolean value) {
253 | throw new IllegalArgumentException ("unknown feature "+name);
254 | }
255 |
256 | /**
257 | * Set the output to the given writer. Wbxml requires an OutputStream.
258 | */
259 | public void setOutput (Writer writer) {
260 | throw new RuntimeException ("Wbxml requires an OutputStream!");
261 | }
262 |
263 | /**
264 | * Set to use binary output stream with given encoding.
265 | */
266 | public void setOutput (OutputStream out, String encoding) throws IOException {
267 |
268 | this.encoding = encoding == null ? "UTF-8" : encoding;
269 | this.out = out;
270 |
271 | buf = new ByteArrayOutputStream();
272 | stringTableBuf = new ByteArrayOutputStream();
273 | headerSent = false;
274 |
275 | // ok, write header
276 | }
277 |
278 | /**
279 | * Binds the given prefix to the given namespace. Not yet implemented.
280 | */
281 | public void setPrefix(String prefix, String nsp) {
282 | throw new RuntimeException("NYI");
283 | }
284 |
285 | /**
286 | * Set the value of a property. There are no supported properties.
287 | */
288 | public void setProperty(String property, Object value) {
289 | throw new IllegalArgumentException ("unknown property "+property);
290 | }
291 |
292 | /**
293 | * Write version and encoding information.
294 | * This method can only be called just after setOutput.
295 | * @param encoding Document encoding. Default is UTF-8.
296 | * @param standalone Not used in WBXML.
297 | */
298 | public void startDocument(String encoding, Boolean standalone) throws IOException {
299 | out.write(0x03); // version 1.3
300 | // http://www.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.htm
301 | out.write(0x01); // unknown or missing public identifier
302 |
303 | // default encoding is UTF-8
304 |
305 | if(encoding != null){
306 | this.encoding = encoding;
307 | }
308 |
309 | if (this.encoding.toUpperCase().equals("UTF-8")){
310 | out.write(106);
311 | }else if (this.encoding.toUpperCase().equals("ISO-8859-1")){
312 | out.write(0x04);
313 | }else{
314 | throw new UnsupportedEncodingException(encoding);
315 | }
316 | }
317 |
318 |
319 | public XmlSerializer startTag(String namespace, String name) throws IOException {
320 |
321 | if (namespace != null && !"".equals(namespace))
322 | throw new RuntimeException ("NSP NYI");
323 |
324 | //current = new State(current, prefixMap, name);
325 |
326 | checkPending(false);
327 | pending = name;
328 | depth++;
329 |
330 | return this;
331 | }
332 |
333 | public XmlSerializer text(char[] chars, int start, int len) throws IOException {
334 | checkPending(false);
335 | writeStr(new String(chars, start, len));
336 | return this;
337 | }
338 |
339 | public XmlSerializer text(String text) throws IOException {
340 | checkPending(false);
341 | writeStr(text);
342 | return this;
343 | }
344 |
345 | /**
346 | * Used in text() and attribute() to write text.
347 | */
348 | private void writeStr(String text) throws IOException{
349 | int p0 = 0;
350 | int lastCut = 0;
351 | int len = text.length();
352 |
353 | if (headerSent) {
354 | writeStrI(buf, text);
355 | return;
356 | }
357 |
358 | while(p0 < len){
359 | while(p0 < len && text.charAt(p0) < 'A' ){ // skip interpunctation
360 | p0++;
361 | }
362 | int p1 = p0;
363 | while (p1 < len && text.charAt(p1) >= 'A'){
364 | p1++;
365 | }
366 |
367 | if (p1 - p0 > 10) {
368 | if (p0 > lastCut && text.charAt(p0-1) == ' '
369 | && stringTable.get(text.substring(p0, p1)) == null){
370 | buf.write(Wbxml.STR_T);
371 | writeStrT(text.substring(lastCut, p1), false);
372 | }
373 | else {
374 | if(p0 > lastCut && text.charAt(p0-1) == ' '){
375 | p0--;
376 | }
377 |
378 | if(p0 > lastCut){
379 | buf.write(Wbxml.STR_T);
380 | writeStrT(text.substring(lastCut, p0), false);
381 | }
382 | buf.write(Wbxml.STR_T);
383 | writeStrT(text.substring(p0, p1), true);
384 | }
385 | lastCut = p1;
386 | }
387 | p0 = p1;
388 | }
389 |
390 | if(lastCut < len){
391 | buf.write(Wbxml.STR_T);
392 | writeStrT(text.substring(lastCut, len), false);
393 | }
394 | }
395 |
396 |
397 |
398 | public XmlSerializer endTag(String namespace, String name) throws IOException {
399 | // current = current.prev;
400 | if (pending != null) {
401 | checkPending(true);
402 | } else {
403 | buf.write(Wbxml.END);
404 | }
405 | depth--;
406 | return this;
407 | }
408 |
409 | /**
410 | * @throws IOException
411 | */
412 | public void writeWapExtension(int type, Object data) throws IOException {
413 | checkPending(false);
414 | buf.write(type);
415 | switch(type){
416 | case Wbxml.EXT_0:
417 | case Wbxml.EXT_1:
418 | case Wbxml.EXT_2:
419 | break;
420 |
421 | case Wbxml.OPAQUE:
422 | byte[] bytes = (byte[]) data;
423 | writeInt(buf, bytes.length);
424 | buf.write(bytes);
425 | break;
426 |
427 | case Wbxml.EXT_I_0:
428 | case Wbxml.EXT_I_1:
429 | case Wbxml.EXT_I_2:
430 | writeStrI(buf, (String) data);
431 | break;
432 |
433 | case Wbxml.EXT_T_0:
434 | case Wbxml.EXT_T_1:
435 | case Wbxml.EXT_T_2:
436 | writeStrT((String) data, false);
437 | break;
438 |
439 | default:
440 | throw new IllegalArgumentException();
441 | }
442 | }
443 |
444 | // ------------- internal methods --------------------------
445 |
446 | static void writeInt(OutputStream out, int i) throws IOException {
447 | byte[] buf = new byte[5];
448 | int idx = 0;
449 |
450 | do {
451 | buf[idx++] = (byte) (i & 0x7f);
452 | i = i >> 7;
453 | }
454 | while (i != 0);
455 |
456 | while (idx > 1) {
457 | out.write(buf[--idx] | 0x80);
458 | }
459 | out.write(buf[0]);
460 | }
461 |
462 | void writeStrI(OutputStream out, String s) throws IOException {
463 | byte[] data = s.getBytes(encoding);
464 | out.write(data);
465 | out.write(0);
466 | }
467 |
468 | private final void writeStrT(String s, boolean mayPrependSpace) throws IOException {
469 |
470 | Integer idx = (Integer) stringTable.get(s);
471 | writeInt(buf, idx == null
472 | ? addToStringTable(s, mayPrependSpace)
473 | : idx.intValue());
474 | }
475 |
476 |
477 | /**
478 | * Add string to string table. Not permitted after string table has been flushed.
479 | *
480 | * @param s string to be added to the string table
481 | * @param mayPrependSpace is set, a space is prepended to the string to archieve better compression results
482 | * @return offset of s in the string table
483 | */
484 | public int addToStringTable(String s, boolean mayPrependSpace) throws IOException {
485 | if (headerSent) {
486 | throw new IOException("stringtable sent");
487 | }
488 |
489 | int i = stringTableBuf.size();
490 | int offset = i;
491 | if(s.charAt(0) >= '0' && mayPrependSpace){
492 | s = ' ' + s;
493 | offset++;
494 | }
495 |
496 | stringTable.put(s, new Integer(i));
497 | if(s.charAt(0) == ' '){
498 | stringTable.put(s.substring(1), new Integer(i+1));
499 | }
500 | int j = s.lastIndexOf(' ');
501 | if(j > 1){
502 | String t = s.substring(j);
503 | int k = t.getBytes("utf-8").length;
504 | stringTable.put(t, new Integer(i+k));
505 | stringTable.put(s.substring(j+1), new Integer(i+k+1));
506 | }
507 |
508 | writeStrI(stringTableBuf, s);
509 | stringTableBuf.flush();
510 | return offset;
511 | }
512 |
513 | /**
514 | * Sets the tag table for a given page.
515 | * The first string in the array defines tag 5, the second tag 6 etc.
516 | */
517 | public void setTagTable(int page, String[] tagTable) {
518 | // TODO: clear entries in tagTable?
519 |
520 | for (int i = 0; i < tagTable.length; i++) {
521 | if (tagTable[i] != null) {
522 | Object idx = new int[]{page, i+5};
523 | this.tagTable.put(tagTable[i], idx);
524 | }
525 | }
526 | }
527 |
528 | /**
529 | * Sets the attribute start Table for a given page.
530 | * The first string in the array defines attribute
531 | * 5, the second attribute 6 etc.
532 | * Please use the
533 | * character '=' (without quote!) as delimiter
534 | * between the attribute name and the (start of the) value
535 | */
536 | public void setAttrStartTable(int page, String[] attrStartTable) {
537 |
538 | for (int i = 0; i < attrStartTable.length; i++) {
539 | if (attrStartTable[i] != null) {
540 | Object idx = new int[] {page, i + 5};
541 | this.attrStartTable.put(attrStartTable[i], idx);
542 | }
543 | }
544 | }
545 |
546 | /**
547 | * Sets the attribute value Table for a given page.
548 | * The first string in the array defines attribute value 0x85,
549 | * the second attribute value 0x86 etc.
550 | * Must be called BEFORE use attribute(), flush() etc.
551 | */
552 | public void setAttrValueTable(int page, String[] attrValueTable) {
553 | // clear entries in this.table!
554 | for (int i = 0; i < attrValueTable.length; i++) {
555 | if (attrValueTable[i] != null) {
556 | Object idx = new int[]{page, i + 0x085};
557 | this.attrValueTable.put(attrValueTable[i], idx);
558 | }
559 | }
560 | }
561 | }
562 |
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/wap/syncml/SyncML.java:
--------------------------------------------------------------------------------
1 | package org.kxml2.wap.syncml;
2 |
3 | import org.kxml2.wap.*;
4 |
5 | public abstract class SyncML {
6 |
7 |
8 | // SyncML-Common (-//SYNCML//DTD SyncML 1.2//EN and -//SYNCML//DTD MetInf 1.2//EN) support
9 |
10 | public static WbxmlParser createParser() {
11 | WbxmlParser p = new WbxmlParser();
12 | p.setTagTable(0, TAG_TABLE_0);
13 | p.setTagTable(1, TAG_TABLE_1);
14 | return p;
15 | }
16 |
17 | public static WbxmlSerializer createSerializer() {
18 | WbxmlSerializer s = new WbxmlSerializer();
19 | s.setTagTable(0, TAG_TABLE_0);
20 | s.setTagTable(1, TAG_TABLE_1);
21 | return s;
22 | }
23 |
24 |
25 | // SyncML-Common + DMDDF (-//OMA//DTD-DM-DDF 1.2//EN) support
26 |
27 | public static WbxmlParser createDMParser() {
28 | WbxmlParser p = createParser();
29 | p.setTagTable(2, TAG_TABLE_2_DM);
30 | return p;
31 | }
32 |
33 | public static WbxmlSerializer createDMSerializer() {
34 | WbxmlSerializer s = createSerializer();
35 | s.setTagTable(2, TAG_TABLE_2_DM);
36 | return s;
37 | }
38 |
39 | // Tables
40 |
41 | public static final String [] TAG_TABLE_0 = {
42 |
43 | // -//SYNCML//DTD SyncML 1.2//EN
44 |
45 | "Add", // 0x05
46 | "Alert", // 0x06
47 | "Archive", // 0x07
48 | "Atomic", // 0x08
49 | "Chal", // 0x09
50 | "Cmd", // 0x0a
51 | "CmdID", // 0x0b
52 | "CmdRef", // 0x0c
53 | "Copy", // 0x0d
54 | "Cred", // 0x0e
55 | "Data", // 0x0f
56 | "Delete", // 0x10
57 | "Exec", // 0x11
58 | "Final", // 0x12
59 | "Get", // 0x13
60 | "Item", // 0x14
61 | "Lang", // 0x15
62 | "LocName", // 0x16
63 | "LocURI", // 0x17
64 | "Map", // 0x18
65 | "MapItem", // 0x19
66 | "Meta", // 0x1a
67 | "MsgID", // 0x1b
68 | "MsgRef", // 0x1c
69 | "NoResp", // 0x1d
70 | "NoResults", // 0x1e
71 | "Put", // 0x1f
72 | "Replace", // 0x20
73 | "RespURI", // 0x21
74 | "Results", // 0x22
75 | "Search", // 0x23
76 | "Sequence", // 0x24
77 | "SessionID", // 0x25
78 | "SftDel", // 0x26
79 | "Source", // 0x27
80 | "SourceRef", // 0x28
81 | "Status", // 0x29
82 | "Sync", // 0x2a
83 | "SyncBody", // 0x2b
84 | "SyncHdr", // 0x2c
85 | "SyncML", // 0x2d
86 | "Target", // 0x2e
87 | "TargetRef", // 0x2f
88 | "Reserved for future use", // 0x30
89 | "VerDTD", // 0x31
90 | "VerProto", // 0x32
91 | "NumberOfChanged",// 0x33
92 | "MoreData", // 0x34
93 | "Field", // 0x35
94 | "Filter", // 0x36
95 | "Record", // 0x37
96 | "FilterType", // 0x38
97 | "SourceParent", // 0x39
98 | "TargetParent", // 0x3a
99 | "Move", // 0x3b
100 | "Correlator" // 0x3c
101 | };
102 |
103 | public static final String [] TAG_TABLE_1 = {
104 |
105 | // -//SYNCML//DTD MetInf 1.2//EN
106 |
107 | "Anchor", // 0x05
108 | "EMI", // 0x06
109 | "Format", // 0x07
110 | "FreeID", // 0x08
111 | "FreeMem", // 0x09
112 | "Last", // 0x0a
113 | "Mark", // 0x0b
114 | "MaxMsgSize", // 0x0c
115 | "Mem", // 0x0d
116 | "MetInf", // 0x0e
117 | "Next", // 0x0f
118 | "NextNonce", // 0x10
119 | "SharedMem", // 0x11
120 | "Size", // 0x12
121 | "Type", // 0x13
122 | "Version", // 0x14
123 | "MaxObjSize", // 0x15
124 | "FieldLevel" // 0x16
125 |
126 | };
127 |
128 | public static final String [] TAG_TABLE_2_DM = {
129 |
130 | // -//OMA//DTD-DM-DDF 1.2//EN
131 |
132 | "AccessType", // 0x05
133 | "ACL", // 0x06
134 | "Add", // 0x07
135 | "b64", // 0x08
136 | "bin", // 0x09
137 | "bool", // 0x0a
138 | "chr", // 0x0b
139 | "CaseSense", // 0x0c
140 | "CIS", // 0x0d
141 | "Copy", // 0x0e
142 | "CS", // 0x0f
143 | "date", // 0x10
144 | "DDFName", // 0x11
145 | "DefaultValue", // 0x12
146 | "Delete", // 0x13
147 | "Description", // 0x14
148 | "DDFFormat", // 0x15
149 | "DFProperties", // 0x16
150 | "DFTitle", // 0x17
151 | "DFType", // 0x18
152 | "Dynamic", // 0x19
153 | "Exec", // 0x1a
154 | "float", // 0x1b
155 | "Format", // 0x1c
156 | "Get", // 0x1d
157 | "int", // 0x1e
158 | "Man", // 0x1f
159 | "MgmtTree", // 0x20
160 | "MIME", // 0x21
161 | "Mod", // 0x22
162 | "Name", // 0x23
163 | "Node", // 0x24
164 | "node", // 0x25
165 | "NodeName", // 0x26
166 | "null", // 0x27
167 | "Occurence", // 0x28
168 | "One", // 0x29
169 | "OneOrMore", // 0x2a
170 | "OneOrN", // 0x2b
171 | "Path", // 0x2c
172 | "Permanent", // 0x2d
173 | "Replace", // 0x2e
174 | "RTProperties", // 0x2f
175 | "Scope", // 0x30
176 | "Size", // 0x31
177 | "time", // 0x32
178 | "Title", // 0x33
179 | "TStamp", // 0x34
180 | "Type", // 0x35
181 | "Value", // 0x36
182 | "VerDTD", // 0x37
183 | "VerNo", // 0x38
184 | "xml", // 0x39
185 | "ZeroOrMore", // 0x3a
186 | "ZeroOrN", // 0x3b
187 | "ZeroOrOne" // 0x3c
188 |
189 | };
190 |
191 | }
192 |
193 |
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/wap/wml/Wml.java:
--------------------------------------------------------------------------------
1 | package org.kxml2.wap.wml;
2 |
3 | import org.kxml2.wap.*;
4 |
5 |
6 | /** This class contains the wml coding tables for elements
7 | * and attributes needed by the WmlParser.
8 | */
9 |
10 |
11 | public abstract class Wml {
12 |
13 | /** Creates a WbxmlParser with the WML code pages set */
14 |
15 | public static WbxmlParser createParser() {
16 | WbxmlParser p = new WbxmlParser();
17 | p.setTagTable(0, TAG_TABLE);
18 | p.setAttrStartTable(0, ATTR_START_TABLE);
19 | p.setAttrValueTable(0, ATTR_VALUE_TABLE);
20 | return p;
21 | }
22 |
23 | public static WbxmlSerializer createSerializer() {
24 | WbxmlSerializer s = new WbxmlSerializer();
25 | s.setTagTable(0, TAG_TABLE);
26 | s.setAttrStartTable(0, ATTR_START_TABLE);
27 | s.setAttrValueTable(0, ATTR_VALUE_TABLE);
28 | return s;
29 | }
30 |
31 |
32 | public static final String [] TAG_TABLE = {
33 |
34 | null, // 05
35 | null, // 06
36 | null, // 07
37 | null, // 08
38 | null, // 09
39 | null, // 0A
40 | null, // 0B
41 | null, // 0C
42 | null, // 0D
43 | null, // 0E
44 | null, // 0F
45 |
46 | null, // 10
47 | null, // 11
48 | null, // 12
49 | null, // 13
50 | null, // 14
51 | null, // 15
52 | null, // 16
53 | null, // 17
54 | null, // 18
55 | null, // 19
56 | null, // 1A
57 | null, // 1B
58 | "a", // 1C
59 | "td", // 1D
60 | "tr", // 1E
61 | "table", // 1F
62 |
63 | "p", // 20
64 | "postfield", // 21
65 | "anchor", // 22
66 | "access", // 23
67 | "b", // 24
68 | "big", // 25
69 | "br", // 26
70 | "card", // 27
71 | "do", // 28
72 | "em", // 29
73 | "fieldset", // 2A
74 | "go", // 2B
75 | "head", // 2C
76 | "i", // 2D
77 | "img", // 2E
78 | "input", // 2F
79 |
80 | "meta", // 30
81 | "noop", // 31
82 | "prev", // 32
83 | "onevent", // 33
84 | "optgroup", // 34
85 | "option", // 35
86 | "refresh", // 36
87 | "select", // 37
88 | "small", // 38
89 | "strong", // 39
90 | null, // 3A
91 | "template", // 3B
92 | "timer", // 3C
93 | "u", // 3D
94 | "setvar", // 3E
95 | "wml", // 3F
96 | };
97 |
98 |
99 | public static final String [] ATTR_START_TABLE = {
100 | "accept-charset", // 05
101 | "align=bottom", // 06
102 | "align=center", // 07
103 | "align=left", // 08
104 | "align=middle", // 09
105 | "align=right", // 0A
106 | "align=top", // 0B
107 | "alt", // 0C
108 | "content", // 0D
109 | null, // 0E
110 | "domain", // 0F
111 |
112 | "emptyok=false", // 10
113 | "emptyok=true", // 11
114 | "format", // 12
115 | "height", // 13
116 | "hspace", // 14
117 | "ivalue", // 15
118 | "iname", // 16
119 | null, // 17
120 | "label", // 18
121 | "localsrc", // 19
122 | "maxlength", // 1A
123 | "method=get", // 1B
124 | "method=post", // 1C
125 | "mode=nowrap", // 1D
126 | "mode=wrap", // 1E
127 | "multiple=false", // 1F
128 |
129 | "multiple=true", // 20
130 | "name", // 21
131 | "newcontext=false", // 22
132 | "newcontext=true", // 23
133 | "onpick", // 24
134 | "onenterbackward", // 25
135 | "onenterforward", // 26
136 | "ontimer", // 27
137 | "optimal=false", // 28
138 | "optimal=true", // 29
139 | "path", // 2A
140 | null, // 2B
141 | null, // 2C
142 | null, // 2D
143 | "scheme", // 2E
144 | "sendreferer=false", // 2F
145 |
146 | "sendreferer=true", // 30
147 | "size", // 31
148 | "src", // 32
149 | "ordered=true", // 33
150 | "ordered=false", // 34
151 | "tabindex", // 35
152 | "title", // 36
153 | "type", // 37
154 | "type=accept", // 38
155 | "type=delete", // 39
156 | "type=help", // 3A
157 | "type=password", // 3B
158 | "type=onpick", // 3C
159 | "type=onenterbackward", // 3D
160 | "type=onenterforward", // 3E
161 | "type=ontimer", // 3F
162 |
163 | null, // 40
164 | null, // 41
165 | null, // 42
166 | null, // 43
167 | null, // 44
168 | "type=options", // 45
169 | "type=prev", // 46
170 | "type=reset", // 47
171 | "type=text", // 48
172 | "type=vnd.", // 49
173 | "href", // 4A
174 | "href=http://", // 4B
175 | "href=https://", // 4C
176 | "value", // 4D
177 | "vspace", // 4E
178 | "width", // 4F
179 |
180 | "xml:lang", // 50
181 | null, // 51
182 | "align", // 52
183 | "columns", // 53
184 | "class", // 54
185 | "id", // 55
186 | "forua=false", // 56
187 | "forua=true", // 57
188 | "src=http://", // 58
189 | "src=https://", // 59
190 | "http-equiv", // 5A
191 | "http-equiv=Content-Type", // 5B
192 | "content=application/vnd.wap.wmlc;charset=", // 5C
193 | "http-equiv=Expires", // 5D
194 | null, // 5E
195 | null, // 5F
196 | };
197 |
198 |
199 | public static final String [] ATTR_VALUE_TABLE = {
200 | ".com/", // 85
201 | ".edu/", // 86
202 | ".net/", // 87
203 | ".org/", // 88
204 | "accept", // 89
205 | "bottom", // 8A
206 | "clear", // 8B
207 | "delete", // 8C
208 | "help", // 8D
209 | "http://", // 8E
210 | "http://www.", // 8F
211 |
212 | "https://", // 90
213 | "https://www.", // 91
214 | null, // 92
215 | "middle", // 93
216 | "nowrap", // 94
217 | "onpick", // 95
218 | "onenterbackward", // 96
219 | "onenterforward", // 97
220 | "ontimer", // 98
221 | "options", // 99
222 | "password", // 9A
223 | "reset", // 9B
224 | null, // 9C
225 | "text", // 9D
226 | "top", // 9E
227 | "unknown", // 9F
228 |
229 | "wrap", // A0
230 | "www.", // A1
231 | };
232 | }
233 |
234 |
--------------------------------------------------------------------------------
/src/main/java/org/kxml2/wap/wv/WV.java:
--------------------------------------------------------------------------------
1 | package org.kxml2.wap.wv;
2 |
3 | import java.io.IOException;
4 |
5 | import org.kxml2.wap.*;
6 |
7 | /*
8 |
9 | * WV.java
10 |
11 | *
12 |
13 | * Created on 25 September 2003, 10:40
14 |
15 | */
16 |
17 |
18 |
19 |
20 |
21 | /**
22 | * Wireless Village CSP 1.1 ("OMA-WV-CSP-V1_1-20021001-A.pdf")
23 | * Wireless Village CSP 1.2 ("OMA-IMPS-WV-CSP_WBXML-v1_2-20030221-C.PDF")
24 | * There are some bugs in the 1.2 spec but this is Ok. 1.2 is candidate
25 | *
26 |
27 | * @author Bogdan Onoiu
28 |
29 | */
30 |
31 | public abstract class WV {
32 |
33 |
34 |
35 |
36 |
37 | public static WbxmlParser createParser () throws IOException {
38 |
39 | WbxmlParser parser = new WbxmlParser();
40 |
41 | parser.setTagTable (0, WV.tagTablePage0);
42 | parser.setTagTable (1, WV.tagTablePage1);
43 | parser.setTagTable (2, WV.tagTablePage2);
44 | parser.setTagTable (3, WV.tagTablePage3);
45 | parser.setTagTable (4, WV.tagTablePage4);
46 | parser.setTagTable (5, WV.tagTablePage5);
47 | parser.setTagTable (6, WV.tagTablePage6);
48 | parser.setTagTable (7, WV.tagTablePage7);
49 | parser.setTagTable (8, WV.tagTablePage8);
50 | parser.setTagTable (9, WV.tagTablePage9);
51 | parser.setTagTable (10, WV.tagTablePageA);
52 |
53 | parser.setAttrStartTable (0, WV.attrStartTable);
54 |
55 | parser.setAttrValueTable (0, WV.attrValueTable);
56 |
57 | return parser;
58 | }
59 |
60 |
61 |
62 | public static final String [] tagTablePage0 = {
63 | /* Common ... continue on Page 0x09 */
64 | "Acceptance", //0x00, 0x05
65 | "AddList", //0x00, 0x06
66 | "AddNickList", //0x00, 0x07
67 | "SName", //0x00, 0x08
68 | "WV-CSP-Message", //0x00, 0x09
69 | "ClientID", //0x00, 0x0A
70 | "Code", //0x00, 0x0B
71 | "ContactList", //0x00, 0x0C
72 | "ContentData", //0x00, 0x0D
73 | "ContentEncoding",//0x00, 0x0E
74 | "ContentSize", //0x00, 0x0F
75 | "ContentType", //0x00, 0x10
76 | "DateTime", //0x00, 0x11
77 | "Description", //0x00, 0x12
78 | "DetailedResult", //0x00, 0x13
79 | "EntityList", //0x00, 0x14
80 | "Group", //0x00, 0x15
81 | "GroupID", //0x00, 0x16
82 | "GroupList", //0x00, 0x17
83 | "InUse", //0x00, 0x18
84 | "Logo", //0x00, 0x19
85 | "MessageCount", //0x00, 0x1A
86 | "MessageID", //0x00, 0x1B
87 | "MessageURI", //0x00, 0x1C
88 | "MSISDN", //0x00, 0x1D
89 | "Name", //0x00, 0x1E
90 | "NickList", //0x00, 0x1F
91 | "NickName", //0x00, 0x20
92 | "Poll", //0x00, 0x21
93 | "Presence", //0x00, 0x22
94 | "PresenceSubList",//0x00, 0x23
95 | "PresenceValue", //0x00, 0x24
96 | "Property", //0x00, 0x25
97 | "Qualifier", //0x00, 0x26
98 | "Recipient", //0x00, 0x27
99 | "RemoveList", //0x00, 0x28
100 | "RemoveNickList", //0x00, 0x29
101 | "Result", //0x00, 0x2A
102 | "ScreenName", //0x00, 0x2B
103 | "Sender", //0x00, 0x2C
104 | "Session", //0x00, 0x2D
105 | "SessionDescriptor",//0x00, 0x2E
106 | "SessionID", //0x00, 0x2F
107 | "SessionType", //0x00, 0x30
108 | "Status", //0x00, 0x31
109 | "Transaction", //0x00, 0x32
110 | "TransactionContent",//0x00, 0x33
111 | "TransactionDescriptor",//0x00, 0x34
112 | "TransactionID", //0x00, 0x35
113 | "TransactionMode",//0x00, 0x36
114 | "URL", //0x00, 0x37
115 | "URLList", //0x00, 0x38
116 | "User", //0x00, 0x39
117 | "UserID", //0x00, 0x3A
118 | "UserList", //0x00, 0x3B
119 | "Validity", //0x00, 0x3C
120 | "Value", //0x00, 0x3D
121 | };
122 |
123 | public static final String [] tagTablePage1 = {
124 | /* Access ... continue on Page 0x0A */
125 | "AllFunctions", // 0x01, 0x05
126 | "AllFunctionsRequest", // 0x01, 0x06
127 | "CancelInvite-Request", // 0x01, 0x07
128 | "CancelInviteUser-Request", // 0x01, 0x08
129 | "Capability", // 0x01, 0x09
130 | "CapabilityList", // 0x01, 0x0A
131 | "CapabilityRequest", // 0x01, 0x0B
132 | "ClientCapability-Request", // 0x01, 0x0C
133 | "ClientCapability-Response",// 0x01, 0x0D
134 | "DigestBytes", // 0x01, 0x0E
135 | "DigestSchema", // 0x01, 0x0F
136 | "Disconnect", // 0x01, 0x10
137 | "Functions", // 0x01, 0x11
138 | "GetSPInfo-Request", // 0x01, 0x12
139 | "GetSPInfo-Response", // 0x01, 0x13
140 | "InviteID", // 0x01, 0x14
141 | "InviteNote", // 0x01, 0x15
142 | "Invite-Request", // 0x01, 0x16
143 | "Invite-Response", // 0x01, 0x17
144 | "InviteType", // 0x01, 0x18
145 | "InviteUser-Request", // 0x01, 0x19
146 | "InviteUser-Response", // 0x01, 0x1A
147 | "KeepAlive-Request", // 0x01, 0x1B
148 | "KeepAliveTime", // 0x01, 0x1C
149 | "Login-Request", // 0x01, 0x1D
150 | "Login-Response", // 0x01, 0x1E
151 | "Logout-Request", // 0x01, 0x1F
152 | "Nonce", // 0x01, 0x20
153 | "Password", // 0x01, 0x21
154 | "Polling-Request", // 0x01, 0x22
155 | "ResponseNote", // 0x01, 0x23
156 | "SearchElement", // 0x01, 0x24
157 | "SearchFindings", // 0x01, 0x25
158 | "SearchID", // 0x01, 0x26
159 | "SearchIndex", // 0x01, 0x27
160 | "SearchLimit", // 0x01, 0x28
161 | "KeepAlive-Response", // 0x01, 0x29
162 | "SearchPairList", // 0x01, 0x2A
163 | "Search-Request", // 0x01, 0x2B
164 | "Search-Response", // 0x01, 0x2C
165 | "SearchResult", // 0x01, 0x2D
166 | "Service-Request", // 0x01, 0x2E
167 | "Service-Response", // 0x01, 0x2F
168 | "SessionCookie", // 0x01, 0x30
169 | "StopSearch-Request", // 0x01, 0x31
170 | "TimeToLive", // 0x01, 0x32
171 | "SearchString", // 0x01, 0x33
172 | "CompletionFlag", // 0x01, 0x34
173 | null, // 0x01, 0x35
174 | "ReceiveList", // 0x01, 0x36 /* WV 1.2 */
175 | "VerifyID-Request", // 0x01, 0x37 /* WV 1.2 */
176 | "Extended-Request", // 0x01, 0x38 /* WV 1.2 */
177 | "Extended-Response", // 0x01, 0x39 /* WV 1.2 */
178 | "AgreedCapabilityList", // 0x01, 0x3A /* WV 1.2 */
179 | "Extended-Data", // 0x01, 0x3B /* WV 1.2 */
180 | "OtherServer", // 0x01, 0x3C /* WV 1.2 */
181 | "PresenceAttributeNSName",//0x01, 0x3D /* WV 1.2 */
182 | "SessionNSName", // 0x01, 0x3E /* WV 1.2 */
183 | "TransactionNSName", // 0x01, 0x3F /* WV 1.2 */
184 | };
185 |
186 | public static final String [] tagTablePage2 = {
187 | /* Service ... continue on Page 0x08 */
188 | "ADDGM", // 0x02, 0x05
189 | "AttListFunc", // 0x02, 0x06
190 | "BLENT", // 0x02, 0x07
191 | "CAAUT", // 0x02, 0x08
192 | "CAINV", // 0x02, 0x09
193 | "CALI", // 0x02, 0x0A
194 | "CCLI", // 0x02, 0x0B
195 | "ContListFunc", // 0x02, 0x0C
196 | "CREAG", // 0x02, 0x0D
197 | "DALI", // 0x02, 0x0E
198 | "DCLI", // 0x02, 0x0F
199 | "DELGR", // 0x02, 0x10
200 | "FundamentalFeat",//0x02, 0x11
201 | "FWMSG", // 0x02, 0x12
202 | "GALS", // 0x02, 0x13
203 | "GCLI", // 0x02, 0x14
204 | "GETGM", // 0x02, 0x15
205 | "GETGP", // 0x02, 0x16
206 | "GETLM", // 0x02, 0x17
207 | "GETM", // 0x02, 0x18
208 | "GETPR", // 0x02, 0x19
209 | "GETSPI", // 0x02, 0x1A
210 | "GETWL", // 0x02, 0x1B
211 | "GLBLU", // 0x02, 0x1C
212 | "GRCHN", // 0x02, 0x1D
213 | "GroupAuthFunc",// 0x02, 0x1E
214 | "GroupFeat", // 0x02, 0x1F
215 | "GroupMgmtFunc",// 0x02, 0x20
216 | "GroupUseFunc", // 0x02, 0x21
217 | "IMAuthFunc", // 0x02, 0x22
218 | "IMFeat", // 0x02, 0x23
219 | "IMReceiveFunc",// 0x02, 0x24
220 | "IMSendFunc", // 0x02, 0x25
221 | "INVIT", // 0x02, 0x26
222 | "InviteFunc", // 0x02, 0x27
223 | "MBRAC", // 0x02, 0x28
224 | "MCLS", // 0x02, 0x29
225 | "MDELIV", // 0x02, 0x2A
226 | "NEWM", // 0x02, 0x2B
227 | "NOTIF", // 0x02, 0x2C
228 | "PresenceAuthFunc",//0x02, 0x2D
229 | "PresenceDeliverFunc",//0x02, 0x2E
230 | "PresenceFeat", // 0x02, 0x2F
231 | "REACT", // 0x02, 0x30
232 | "REJCM", // 0x02, 0x31
233 | "REJEC", // 0x02, 0x32
234 | "RMVGM", // 0x02, 0x33
235 | "SearchFunc", // 0x02, 0x34
236 | "ServiceFunc", // 0x02, 0x35
237 | "SETD", // 0x02, 0x36
238 | "SETGP", // 0x02, 0x37
239 | "SRCH", // 0x02, 0x38
240 | "STSRC", // 0x02, 0x39
241 | "SUBGCN", // 0x02, 0x3A
242 | "UPDPR", // 0x02, 0x3B
243 | "WVCSPFeat", // 0x02, 0x3C
244 | "MF", // 0x02, 0x3D /* WV 1.2 */
245 | "MG", // 0x02, 0x3E /* WV 1.2 */
246 | "MM" // 0x02, 0x3F /* WV 1.2 */
247 | };
248 |
249 | public static final String [] tagTablePage3 = {
250 | /* Client Capability */
251 | "AcceptedCharset", // 0x03, 0x05
252 | "AcceptedContentLength", // 0x03, 0x06
253 | "AcceptedContentType", // 0x03, 0x07
254 | "AcceptedTransferEncoding", // 0x03, 0x08
255 | "AnyContent", // 0x03, 0x09
256 | "DefaultLanguage", // 0x03, 0x0A
257 | "InitialDeliveryMethod", // 0x03, 0x0B
258 | "MultiTrans", // 0x03, 0x0C
259 | "ParserSize", // 0x03, 0x0D
260 | "ServerPollMin", // 0x03, 0x0E
261 | "SupportedBearer", // 0x03, 0x0F
262 | "SupportedCIRMethod", // 0x03, 0x10
263 | "TCPAddress", // 0x03, 0x11
264 | "TCPPort", // 0x03, 0x12
265 | "UDPPort" // 0x03, 0x13
266 | };
267 |
268 | public static final String [] tagTablePage4 = {
269 | /* Presence Primitive */
270 | "CancelAuth-Request", // 0x04, 0x05
271 | "ContactListProperties", // 0x04, 0x06
272 | "CreateAttributeList-Request", // 0x04, 0x07
273 | "CreateList-Request", // 0x04, 0x08
274 | "DefaultAttributeList", // 0x04, 0x09
275 | "DefaultContactList", // 0x04, 0x0A
276 | "DefaultList", // 0x04, 0x0B
277 | "DeleteAttributeList-Request", // 0x04, 0x0C
278 | "DeleteList-Request", // 0x04, 0x0D
279 | "GetAttributeList-Request", // 0x04, 0x0E
280 | "GetAttributeList-Response", // 0x04, 0x0F
281 | "GetList-Request", // 0x04, 0x10
282 | "GetList-Response", // 0x04, 0x11
283 | "GetPresence-Request", // 0x04, 0x12
284 | "GetPresence-Response", // 0x04, 0x13
285 | "GetWatcherList-Request", // 0x04, 0x14
286 | "GetWatcherList-Response", // 0x04, 0x15
287 | "ListManage-Request", // 0x04, 0x16
288 | "ListManage-Response", // 0x04, 0x17
289 | "UnsubscribePresence-Request", // 0x04, 0x18
290 | "PresenceAuth-Request", // 0x04, 0x19
291 | "PresenceAuth-User", // 0x04, 0x1A
292 | "PresenceNotification-Request", // 0x04, 0x1B
293 | "UpdatePresence-Request", // 0x04, 0x1C
294 | "SubscribePresence-Request", // 0x04, 0x1D
295 | "Auto-Subscribe", // 0x04, 0x1E /* WV 1.2 */
296 | "GetReactiveAuthStatus-Request",// 0x04, 0x1F /* WV 1.2 */
297 | "GetReactiveAuthStatus-Response",// 0x04, 0x20 /* WV 1.2 */
298 | };
299 |
300 | public static final String [] tagTablePage5 = {
301 | /* Presence Attribute */
302 | "Accuracy", // 0x05, 0x05
303 | "Address", // 0x05, 0x06
304 | "AddrPref", // 0x05, 0x07
305 | "Alias", // 0x05, 0x08
306 | "Altitude", // 0x05, 0x09
307 | "Building", // 0x05, 0x0A
308 | "Caddr", // 0x05, 0x0B
309 | "City", // 0x05, 0x0C
310 | "ClientInfo", // 0x05, 0x0D
311 | "ClientProducer", // 0x05, 0x0E
312 | "ClientType", // 0x05, 0x0F
313 | "ClientVersion", // 0x05, 0x10
314 | "CommC", // 0x05, 0x11
315 | "CommCap", // 0x05, 0x12
316 | "ContactInfo", // 0x05, 0x13
317 | "ContainedvCard", // 0x05, 0x14
318 | "Country", // 0x05, 0x15
319 | "Crossing1", // 0x05, 0x16
320 | "Crossing2", // 0x05, 0x17
321 | "DevManufacturer", // 0x05, 0x18
322 | "DirectContent", // 0x05, 0x19
323 | "FreeTextLocation", // 0x05, 0x1A
324 | "GeoLocation", // 0x05, 0x1B
325 | "Language", // 0x05, 0x1C
326 | "Latitude", // 0x05, 0x1D
327 | "Longitude", // 0x05, 0x1E
328 | "Model", // 0x05, 0x1F
329 | "NamedArea", // 0x05, 0x20
330 | "OnlineStatus", // 0x05, 0x21
331 | "PLMN", // 0x05, 0x22
332 | "PrefC", // 0x05, 0x23
333 | "PreferredContacts",// 0x05, 0x24
334 | "PreferredLanguage",// 0x05, 0x25
335 | "PreferredContent", // 0x05, 0x26
336 | "PreferredvCard", // 0x05, 0x27
337 | "Registration", // 0x05, 0x28
338 | "StatusContent", // 0x05, 0x29
339 | "StatusMood", // 0x05, 0x2A
340 | "StatusText", // 0x05, 0x2B
341 | "Street", // 0x05, 0x2C
342 | "TimeZone", // 0x05, 0x2D
343 | "UserAvailability", // 0x05, 0x2E
344 | "Cap", // 0x05, 0x2F
345 | "Cname", // 0x05, 0x30
346 | "Contact", // 0x05, 0x31
347 | "Cpriority", // 0x05, 0x32
348 | "Cstatus", // 0x05, 0x33
349 | "Note", // 0x05, 0x34 /* WV 1.2 */
350 | "Zone", // 0x05, 0x35
351 | null,
352 | "Inf_link", // 0x05, 0x37 /* WV 1.2 */
353 | "InfoLink", // 0x05, 0x38 /* WV 1.2 */
354 | "Link", // 0x05, 0x39 /* WV 1.2 */
355 | "Text", // 0x05, 0x3A /* WV 1.2 */
356 | };
357 |
358 | public static final String [] tagTablePage6 = {
359 | /* Messaging */
360 | "BlockList", // 0x06, 0x05
361 | // "BlockUser-Request", // 0x06, 0x06 //This is a bug in the spec
362 | "BlockEntity-Request", // 0x06, 0x06
363 | "DeliveryMethod", // 0x06, 0x07
364 | "DeliveryReport", // 0x06, 0x08
365 | "DeliveryReport-Request", // 0x06, 0x09
366 | "ForwardMessage-Request", // 0x06, 0x0A
367 | "GetBlockedList-Request", // 0x06, 0x0B
368 | "GetBlockedList-Response", // 0x06, 0x0C
369 | "GetMessageList-Request", // 0x06, 0x0D
370 | "GetMessageList-Response", // 0x06, 0x0E
371 | "GetMessage-Request", // 0x06, 0x0F
372 | "GetMessage-Response", // 0x06, 0x10
373 | "GrantList", // 0x06, 0x11
374 | "MessageDelivered", // 0x06, 0x12
375 | "MessageInfo", // 0x06, 0x13
376 | "MessageNotification", // 0x06, 0x14
377 | "NewMessage", // 0x06, 0x15
378 | "RejectMessage-Request", // 0x06, 0x16
379 | "SendMessage-Request", // 0x06, 0x17
380 | "SendMessage-Response", // 0x06, 0x18
381 | "SetDeliveryMethod-Request",// 0x06, 0x19
382 | "DeliveryTime", // 0x06, 0x1A
383 | };
384 |
385 | public static final String [] tagTablePage7 = {
386 | /* Group */
387 | "AddGroupMembers-Request", // 0x07, 0x05
388 | "Admin", // 0x07, 0x06
389 | "CreateGroup-Request", // 0x07, 0x07
390 | "DeleteGroup-Request", // 0x07, 0x08
391 | "GetGroupMembers-Request", // 0x07, 0x09
392 | "GetGroupMembers-Response", // 0x07, 0x0A
393 | "GetGroupProps-Request", // 0x07, 0x0B
394 | "GetGroupProps-Response", // 0x07, 0x0C
395 | "GroupChangeNotice", // 0x07, 0x0D
396 | "GroupProperties", // 0x07, 0x0E
397 | "Joined", // 0x07, 0x0F
398 | "JoinedRequest", // 0x07, 0x10
399 | "JoinGroup-Request", // 0x07, 0x11
400 | "JoinGroup-Response", // 0x07, 0x12
401 | "LeaveGroup-Request", // 0x07, 0x13
402 | "LeaveGroup-Response", // 0x07, 0x14
403 | "Left", // 0x07, 0x15
404 | "MemberAccess-Request", // 0x07, 0x16
405 | "Mod", // 0x07, 0x17
406 | "OwnProperties", // 0x07, 0x18
407 | "RejectList-Request", // 0x07, 0x19
408 | "RejectList-Response", // 0x07, 0x1A
409 | "RemoveGroupMembers-Request",// 0x07, 0x1B
410 | "SetGroupProps-Request", // 0x07, 0x1C
411 | "SubscribeGroupNotice-Request", // 0x07, 0x1D
412 | "SubscribeGroupNotice-Response",// 0x07, 0x1E
413 | "Users", // 0x07, 0x1F
414 | "WelcomeNote", // 0x07, 0x20
415 | "JoinGroup", // 0x07, 0x21
416 | "SubscribeNotification", // 0x07, 0x22
417 | "SubscribeType", // 0x07, 0x23
418 | "GetJoinedUsers-Request", // 0x07, 0x24 /* WV 1.2 */
419 | "GetJoinedUsers-Response", // 0x07, 0x25 /* WV 1.2 */
420 | "AdminMapList", // 0x07, 0x26 /* WV 1.2 */
421 | "AdminMapping", // 0x07, 0x27 /* WV 1.2 */
422 | "Mapping", // 0x07, 0x28 /* WV 1.2 */
423 | "ModMapping", // 0x07, 0x29 /* WV 1.2 */
424 | "UserMapList", // 0x07, 0x2A /* WV 1.2 */
425 | "UserMapping", // 0x07, 0x2B /* WV 1.2 */
426 | };
427 |
428 | public static final String [] tagTablePage8 = {
429 | /* Service ... continued */
430 | "MP", // 0x08, 0x05 /* WV 1.2 */
431 | "GETAUT", // 0x08, 0x06 /* WV 1.2 */
432 | "GETJU", // 0x08, 0x07 /* WV 1.2 */
433 | "VRID", // 0x08, 0x08 /* WV 1.2 */
434 | "VerifyIDFunc", // 0x08, 0x09 /* WV 1.2 */
435 | };
436 |
437 | public static final String [] tagTablePage9 = {
438 | /* Common ... continued */
439 | "CIR", // 0x09, 0x05 /* WV 1.2 */
440 | "Domain", // 0x09, 0x06 /* WV 1.2 */
441 | "ExtBlock", // 0x09, 0x07 /* WV 1.2 */
442 | "HistoryPeriod", // 0x09, 0x08 /* WV 1.2 */
443 | "IDList", // 0x09, 0x09 /* WV 1.2 */
444 | "MaxWatcherList", // 0x09, 0x0A /* WV 1.2 */
445 | "ReactiveAuthState", // 0x09, 0x0B /* WV 1.2 */
446 | "ReactiveAuthStatus", // 0x09, 0x0C /* WV 1.2 */
447 | "ReactiveAuthStatusList", // 0x09, 0x0D /* WV 1.2 */
448 | "Watcher", // 0x09, 0x0E /* WV 1.2 */
449 | "WatcherStatus" // 0x09, 0x0F /* WV 1.2 */
450 | };
451 |
452 | public static final String [] tagTablePageA = {
453 | /* Access ... continued */
454 | "WV-CSP-NSDiscovery-Request", //0x0A, 0x05 /* WV 1.2 */
455 | "WV-CSP-NSDiscovery-Response", //0x0A, 0x06 /* WV 1.2 */
456 | "VersionList" //0x0A, 0x07 /* WV 1.2 */
457 | };
458 |
459 | public static final String [] attrStartTable = {
460 | "xmlns=http://www.wireless-village.org/CSP",// 0x00, 0x05
461 | "xmlns=http://www.wireless-village.org/PA", // 0x00, 0x06
462 | "xmlns=http://www.wireless-village.org/TRC",// 0x00, 0x07
463 | "xmlns=http://www.openmobilealliance.org/DTD/WV-CSP", // 0x00, 0x08
464 | "xmlns=http://www.openmobilealliance.org/DTD/WV-PA", // 0x00, 0x09
465 | "xmlns=http://www.openmobilealliance.org/DTD/WV-TRC", // 0x00, 0x0A
466 | };
467 |
468 | public static final String [] attrValueTable = {
469 |
470 | "AccessType", // 0x00 /* Common value token */
471 | "ActiveUsers", // 0x01 /* Common value token */
472 | "Admin", // 0x02 /* Common value token */
473 | "application/", // 0x03 /* Common value token */
474 | "application/vnd.wap.mms-message", // 0x04 /* Common value token */
475 | "application/x-sms", // 0x05 /* Common value token */
476 | "AutoJoin", // 0x06 /* Common value token */
477 | "BASE64", // 0x07 /* Common value token */
478 | "Closed", // 0x08 /* Common value token */
479 | "Default", // 0x09 /* Common value token */
480 | "DisplayName", // 0x0a /* Common value token */
481 | "F", // 0x0b /* Common value token */
482 | "G", // 0x0c /* Common value token */
483 | "GR", // 0x0d /* Common value token */
484 | "http://", // 0x0e /* Common value token */
485 | "https://", // 0x0f /* Common value token */
486 | "image/", // 0x10 /* Common value token */
487 | "Inband", // 0x11 /* Common value token */
488 | "IM", // 0x12 /* Common value token */
489 | "MaxActiveUsers", // 0x13 /* Common value token */
490 | "Mod", // 0x14 /* Common value token */
491 | "Name", // 0x15 /* Common value token */
492 | "None", // 0x16 /* Common value token */
493 | "N", // 0x17 /* Common value token */
494 | "Open", // 0x18 /* Common value token */
495 | "Outband", // 0x19 /* Common value token */
496 | "PR", // 0x1a /* Common value token */
497 | "Private", // 0x1b /* Common value token */
498 | "PrivateMessaging", // 0x1c /* Common value token */
499 | "PrivilegeLevel", // 0x1d /* Common value token */
500 | "Public", // 0x1e /* Common value token */
501 | "P", // 0x1f /* Common value token */
502 | "Request", // 0x20 /* Common value token */
503 | "Response", // 0x21 /* Common value token */
504 | "Restricted", // 0x22 /* Common value token */
505 | "ScreenName", // 0x23 /* Common value token */
506 | "Searchable", // 0x24 /* Common value token */
507 | "S", // 0x25 /* Common value token */
508 | "SC", // 0x26 /* Common value token */
509 | "text/", // 0x27 /* Common value token */
510 | "text/plain", // 0x28 /* Common value token */
511 | "text/x-vCalendar", // 0x29 /* Common value token */
512 | "text/x-vCard", // 0x2a /* Common value token */
513 | "Topic", // 0x2b /* Common value token */
514 | "T", // 0x2c /* Common value token */
515 | "Type", // 0x2d /* Common value token */
516 | "U", // 0x2e /* Common value token */
517 | "US", // 0x2f /* Common value token */
518 | "www.wireless-village.org", // 0x30 /* Common value token */
519 | "AutoDelete", // 0x31 /* Common value token */ /* WV 1.2 */
520 | "GM", // 0x32 /* Common value token */ /* WV 1.2 */
521 | "Validity", // 0x33 /* Common value token */ /* WV 1.2 */
522 | "ShowID", // 0x34 /* Common value token */ /* WV 1.2 */
523 | "GRANTED", // 0x35 /* Common value token */ /* WV 1.2 */
524 | "PENDING", // 0x36 /* Common value token */ /* WV 1.2 */
525 | null, // 0x37
526 | null, // 0x38
527 | null, // 0x39
528 | null, // 0x3a
529 | null, // 0x3b
530 | null, // 0x3c
531 | "GROUP_ID", // 0x3d /* Access value token */
532 | "GROUP_NAME", // 0x3e /* Access value token */
533 | "GROUP_TOPIC", // 0x3f /* Access value token */
534 | "GROUP_USER_ID_JOINED", // 0x40 /* Access value token */
535 | "GROUP_USER_ID_OWNER", // 0x41 /* Access value token */
536 | "HTTP", // 0x42 /* Access value token */
537 | "SMS", // 0x43 /* Access value token */
538 | "STCP", // 0x44 /* Access value token */
539 | "SUDP", // 0x45 /* Access value token */
540 | "USER_ALIAS", // 0x46 /* Access value token */
541 | "USER_EMAIL_ADDRESS", // 0x47 /* Access value token */
542 | "USER_FIRST_NAME", // 0x48 /* Access value token */
543 | "USER_ID", // 0x49 /* Access value token */
544 | "USER_LAST_NAME", // 0x4a /* Access value token */
545 | "USER_MOBILE_NUMBER", // 0x4b /* Access value token */
546 | "USER_ONLINE_STATUS", // 0x4c /* Access value token */
547 | "WAPSMS", // 0x4d /* Access value token */
548 | "WAPUDP", // 0x4e /* Access value token */
549 | "WSP", // 0x4f /* Access value token */
550 | "GROUP_USER_ID_AUTOJOIN", // 0x50 /* Access value token */ /* WV 1.2 */
551 | null, // 0x51
552 | null, // 0x52
553 | null, // 0x53
554 | null, // 0x54
555 | null, // 0x55
556 | null, // 0x56
557 | null, // 0x57
558 | null, // 0x58
559 | null, // 0x59
560 | null, // 0x5a
561 | "ANGRY", // 0x5b /* Presence value token */
562 | "ANXIOUS", // 0x5c /* Presence value token */
563 | "ASHAMED", // 0x5d /* Presence value token */
564 | "AUDIO_CALL", // 0x5e /* Presence value token */
565 | "AVAILABLE", // 0x5f /* Presence value token */
566 | "BORED", // 0x60 /* Presence value token */
567 | "CALL", // 0x61 /* Presence value token */
568 | "CLI", // 0x62 /* Presence value token */
569 | "COMPUTER", // 0x63 /* Presence value token */
570 | "DISCREET", // 0x64 /* Presence value token */
571 | "EMAIL", // 0x65 /* Presence value token */
572 | "EXCITED", // 0x66 /* Presence value token */
573 | "HAPPY", // 0x67 /* Presence value token */
574 | "IM", // 0x68 /* Presence value token */
575 | "IM_OFFLINE", // 0x69 /* Presence value token */
576 | "IM_ONLINE", // 0x6a /* Presence value token */
577 | "IN_LOVE", // 0x6b /* Presence value token */
578 | "INVINCIBLE", // 0x6c /* Presence value token */
579 | "JEALOUS", // 0x6d /* Presence value token */
580 | "MMS", // 0x6e /* Presence value token */
581 | "MOBILE_PHONE", // 0x6f /* Presence value token */
582 | "NOT_AVAILABLE", // 0x70 /* Presence value token */
583 | "OTHER", // 0x71 /* Presence value token */
584 | "PDA", // 0x72 /* Presence value token */
585 | "SAD", // 0x73 /* Presence value token */
586 | "SLEEPY", // 0x74 /* Presence value token */
587 | "SMS", // 0x75 /* Presence value token */
588 | "VIDEO_CALL", // 0x76 /* Presence value token */
589 | "VIDEO_STREAM", // 0x77 /* Presence value token */
590 | };
591 |
592 |
593 | }
--------------------------------------------------------------------------------
/src/main/resources/META-INF/services/org.xmlpull.v1.XmlPullParserFactory:
--------------------------------------------------------------------------------
1 | org.kxml2.io.KXmlParser
2 | org.kxml2.io.KXmlSerializer
3 |
--------------------------------------------------------------------------------
/src/test/java/TestWb.java:
--------------------------------------------------------------------------------
1 | // Test case contributed by Andy Bailey
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.File;
6 | import java.io.FileNotFoundException;
7 | import java.io.FileOutputStream;
8 | import java.io.IOException;
9 | import java.io.StringReader;
10 | import java.io.StringWriter;
11 | import java.nio.charset.StandardCharsets;
12 | import junit.framework.TestCase;
13 |
14 | import org.kxml2.wap.Wbxml;
15 | import org.kxml2.wap.WbxmlSerializer;
16 | import org.xmlpull.v1.XmlPullParser;
17 | import org.xmlpull.v1.XmlPullParserException;
18 | import org.xmlpull.v1.XmlPullParserFactory;
19 | import org.xmlpull.v1.XmlSerializer;
20 |
21 | public class TestWb extends TestCase
22 | {
23 | public void disabled_testWb() throws IllegalArgumentException,IllegalStateException, FileNotFoundException, IOException
24 | {
25 | File file=new File("compress.xml");
26 |
27 | WbxmlSerializer xs = new WbxmlSerializer();
28 | boolean compress=true;
29 |
30 | xs.setOutput(new FileOutputStream(file),null);
31 | //xs.setOutput(System.out,"UTF-8");
32 | //xs.docdecl();
33 | //xs.setPrefix("","http://www.hazlorealidad.com");
34 | //xs.startDocument("UTF-8",true);
35 | xs.startDocument(null,null);
36 | //xs.comment("Comment");
37 | xs.startTag(null,"root");
38 | xs.startTag(null,"y");
39 | xs.attribute(null,"name","value");
40 | xs.writeWapExtension(Wbxml.EXT_T_1,new Integer(2));
41 | xs.endTag(null,"y");
42 | xs.startTag(null,"y");
43 | xs.attribute(null,"name","value");
44 | xs.writeWapExtension(Wbxml.EXT_T_1,new Integer(2));
45 | xs.endTag(null,"y");
46 | xs.endTag(null,"root");
47 | xs.endDocument();
48 | xs.flush();
49 | long len=file.length();
50 | System.out.println(len+" bytes");
51 | }
52 |
53 | // Using hex code units to be sure that the system charset does not affect the behavior
54 | private static final String EMOJI_CHAR = "\ud83d\ude48";
55 |
56 | private static final String XML_TO_PARSE = "\n"
57 | + "\n"
58 | + " \n"
59 | + " \n"
60 | + " Emoji: " + EMOJI_CHAR + "🙈🙈\n"
61 | + "\n";
62 |
63 | private static void checkParseBeyondBmp(XmlPullParser xpp) throws XmlPullParserException, IOException {
64 | while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
65 | switch (xpp.getEventType()) {
66 | case XmlPullParser.CDSECT:
67 | assertTrue(xpp.getText().contains(EMOJI_CHAR));
68 | break;
69 | case XmlPullParser.COMMENT:
70 | assertTrue(xpp.getText().contains(EMOJI_CHAR));
71 | break;
72 | case XmlPullParser.TEXT:
73 | final String text = xpp.getText().replaceAll("[\\n\\r\\t ]+", "");
74 | if (!text.isEmpty()) {
75 | assertTrue(xpp.getText().contains(EMOJI_CHAR));
76 | }
77 | break;
78 | case XmlPullParser.ENTITY_REF:
79 | assertEquals(EMOJI_CHAR, xpp.getText());
80 | break;
81 | case XmlPullParser.START_TAG:
82 | for (int i = 0; i < xpp.getAttributeCount(); i++) {
83 | assertEquals(EMOJI_CHAR, xpp.getAttributeValue(i));
84 | }
85 | break;
86 | }
87 | xpp.nextToken();
88 | }
89 | }
90 |
91 | public void testParseBeyondBmpFromReader() throws XmlPullParserException, IOException {
92 | final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
93 | final XmlPullParser xpp = factory.newPullParser();
94 | xpp.setInput(new StringReader(XML_TO_PARSE));
95 |
96 | checkParseBeyondBmp(xpp);
97 | }
98 |
99 | public void testParseBeyondBmpInputStream() throws XmlPullParserException, IOException {
100 | final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
101 | final XmlPullParser xpp = factory.newPullParser();
102 | xpp.setInput(new ByteArrayInputStream(XML_TO_PARSE.getBytes(StandardCharsets.UTF_8)), "utf-8");
103 |
104 | checkParseBeyondBmp(xpp);
105 | }
106 |
107 | private static final String EXPECTED_XML_SERIALIZATION = ""
108 | + "\n"
109 | + "\n"
110 | + "Emoji: 🙈";
111 |
112 | private static void checkSerializeBeyondBmp(XmlSerializer serializer) throws IOException {
113 | final String text = "Emoji: " + EMOJI_CHAR;
114 |
115 | serializer.comment(text);
116 | serializer.text("\n");
117 | serializer.cdsect(text);
118 | serializer.text("\n");
119 | serializer.startTag(null, "string");
120 | serializer.attribute(null, "attr", EMOJI_CHAR);
121 | serializer.text(text);
122 | serializer.endTag(null, "string");
123 | serializer.endDocument();
124 | }
125 |
126 | public void testSerializeBeyondBmpToOutputStream() throws XmlPullParserException, IOException {
127 | final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
128 | factory.setNamespaceAware(true);
129 | final XmlSerializer serializer = factory.newSerializer();
130 |
131 | final ByteArrayOutputStream os = new ByteArrayOutputStream();
132 | serializer.setOutput(os, "utf-8");
133 |
134 | checkSerializeBeyondBmp(serializer);
135 |
136 | assertEquals(EXPECTED_XML_SERIALIZATION, os.toString("utf-8"));
137 | }
138 |
139 | public void testSerializeBeyondBmpToWriter() throws XmlPullParserException, IOException {
140 | final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
141 | factory.setNamespaceAware(true);
142 | final XmlSerializer serializer = factory.newSerializer();
143 |
144 | final StringWriter writer = new StringWriter();
145 | serializer.setOutput(writer);
146 |
147 | checkSerializeBeyondBmp(serializer);
148 |
149 | assertEquals(EXPECTED_XML_SERIALIZATION, writer.toString());
150 | }
151 | }
152 |
153 |
--------------------------------------------------------------------------------