├── demo-scalaxb
├── .gitignore
└── pom.xml
├── file-list-maven-plugin
├── src
│ ├── test
│ │ ├── resources
│ │ │ ├── a
│ │ │ ├── b
│ │ │ └── c
│ │ │ │ ├── d
│ │ │ │ └── e
│ │ │ │ ├── g
│ │ │ │ └── h
│ │ └── java
│ │ │ └── com
│ │ │ └── github
│ │ │ └── davidmoten
│ │ │ └── xsdforms
│ │ │ └── maven
│ │ │ └── FileListerTest.java
│ └── main
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── davidmoten
│ │ └── xsdforms
│ │ └── maven
│ │ ├── FileLister.java
│ │ └── FileListMojo.java
├── .gitignore
└── pom.xml
├── xsd-forms-generator
├── src
│ ├── docs
│ │ ├── showcase
│ │ │ ├── js
│ │ │ │ ├── xsd-forms-override.js
│ │ │ │ └── xml2json.js
│ │ │ └── css
│ │ │ │ ├── xsd-forms-style-override.css
│ │ │ │ ├── smoothness
│ │ │ │ └── images
│ │ │ │ │ ├── ui-icons_222222_256x240.png
│ │ │ │ │ ├── ui-icons_2e83ff_256x240.png
│ │ │ │ │ ├── ui-icons_454545_256x240.png
│ │ │ │ │ ├── ui-icons_888888_256x240.png
│ │ │ │ │ ├── ui-icons_cd0a0a_256x240.png
│ │ │ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ │ │ │ │ ├── ui-bg_flat_75_ffffff_40x100.png
│ │ │ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ │ │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ │ │ │ ├── ui-bg_glass_75_dadada_1x400.png
│ │ │ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ │ │ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png
│ │ │ │ │ └── ui-bg_highlight-soft_75_cccccc_1x100.png
│ │ │ │ ├── timepicker.css
│ │ │ │ └── xsd-forms-style.css
│ │ ├── screen1.png
│ │ └── diagram01.png
│ ├── test
│ │ ├── resources
│ │ │ ├── tick.gif
│ │ │ ├── test-pattern-1.xsd
│ │ │ ├── annotations-demo.xsd
│ │ │ ├── simple.xsd
│ │ │ ├── demo-form-expected.xml
│ │ │ ├── polrep.xsd
│ │ │ └── australian-census-2011.xsd
│ │ └── scala
│ │ │ └── com
│ │ │ └── github
│ │ │ └── davidmoten
│ │ │ ├── util
│ │ │ └── jsTest.scala
│ │ │ └── xsdforms
│ │ │ ├── tree
│ │ │ └── treeUtilTest.scala
│ │ │ ├── tstUtil.scala
│ │ │ └── generatorTest.scala
│ └── main
│ │ ├── scala
│ │ └── com
│ │ │ └── github
│ │ │ └── davidmoten
│ │ │ ├── xsdforms
│ │ │ ├── configuration.scala
│ │ │ ├── tree
│ │ │ │ ├── util.scala
│ │ │ │ ├── node.scala
│ │ │ │ ├── xsd-util.scala
│ │ │ │ ├── form-creator-util.scala
│ │ │ │ ├── ids.scala
│ │ │ │ ├── visitor.scala
│ │ │ │ ├── html
│ │ │ │ │ └── html.scala
│ │ │ │ ├── element-wrapper.scala
│ │ │ │ └── traversor.scala
│ │ │ ├── presentation
│ │ │ │ ├── css.scala
│ │ │ │ └── annotation.scala
│ │ │ └── generator.scala
│ │ │ └── util
│ │ │ └── js.scala
│ │ └── resources
│ │ └── template.html
├── update-samples.sh
└── pom.xml
├── xsd-forms-html-js
├── src
│ └── main
│ │ └── resources
│ │ ├── js
│ │ └── xsd-forms-override.js
│ │ └── css
│ │ ├── xsd-forms-style-override.css
│ │ ├── smoothness
│ │ └── images
│ │ │ ├── ui-icons_222222_256x240.png
│ │ │ ├── ui-icons_2e83ff_256x240.png
│ │ │ ├── ui-icons_454545_256x240.png
│ │ │ ├── ui-icons_888888_256x240.png
│ │ │ ├── ui-icons_cd0a0a_256x240.png
│ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ │ │ ├── ui-bg_flat_75_ffffff_40x100.png
│ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ │ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ │ ├── ui-bg_glass_75_dadada_1x400.png
│ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png
│ │ │ └── ui-bg_highlight-soft_75_cccccc_1x100.png
│ │ ├── timepicker.css
│ │ └── xsd-forms-style.css
├── .gitignore
└── pom.xml
├── .gitignore
├── xsd-forms-maven-plugin-demo
├── src
│ ├── main
│ │ └── js
│ │ │ └── extraScript.js
│ └── test
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── davidmoten
│ │ └── xsdforms
│ │ └── maven
│ │ └── GeneratorMojoTest.java
└── pom.xml
├── Procfile
├── xsd-forms-generator-webapp
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── davidmoten
│ │ │ └── xsdforms
│ │ │ ├── store
│ │ │ └── Datastore.java
│ │ │ └── servlet
│ │ │ └── GeneratorServlet.java
│ │ └── webapp
│ │ └── WEB-INF
│ │ └── web.xml
└── pom.xml
├── xsd-scalaxb
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── davidmoten
│ │ │ └── xsdforms
│ │ │ └── Ignore.java
│ │ └── xsd
│ │ ├── xsd-forms.xsd
│ │ ├── miuml-class.xsd
│ │ ├── datatypes.dtd
│ │ └── xml.xsd
└── pom.xml
├── .github
├── dependabot.yml
└── workflows
│ └── ci.yml
└── xsd-forms-maven-plugin
├── pom.xml
└── src
└── main
└── java
└── com
└── github
└── davidmoten
└── xsdforms
└── maven
└── GenerateMojo.java
/demo-scalaxb/.gitignore:
--------------------------------------------------------------------------------
1 | /bin
2 |
--------------------------------------------------------------------------------
/file-list-maven-plugin/src/test/resources/a:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/file-list-maven-plugin/src/test/resources/b:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/file-list-maven-plugin/src/test/resources/c/d:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/file-list-maven-plugin/src/test/resources/c/e/g:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/file-list-maven-plugin/src/test/resources/c/e/h:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/js/xsd-forms-override.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/js/xsd-forms-override.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/xsd-forms-style-override.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/xsd-forms-style-override.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .settings
3 | .project
4 | .classpath
5 | .cache
6 |
--------------------------------------------------------------------------------
/xsd-forms-html-js/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .classpath
3 | .project
4 | .settings
5 |
--------------------------------------------------------------------------------
/file-list-maven-plugin/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .classpath
3 | .project
4 | .settings
5 |
--------------------------------------------------------------------------------
/xsd-forms-maven-plugin-demo/src/main/js/extraScript.js:
--------------------------------------------------------------------------------
1 |
2 | //extra script goes here
3 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/screen1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/screen1.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/diagram01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/diagram01.png
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: java -jar xsd-forms-generator-webapp/target/dependency/jetty-runner.jar --port $PORT xsd-forms-generator-webapp/target/*.war
2 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/resources/tick.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/test/resources/tick.gif
--------------------------------------------------------------------------------
/xsd-forms-generator/update-samples.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | rm -rf src/docs/showcase
4 | mkdir src/docs/showcase
5 | cp -r target/generated-webapp/* src/docs/showcase
6 |
7 |
--------------------------------------------------------------------------------
/xsd-forms-generator-webapp/src/main/java/com/github/davidmoten/xsdforms/store/Datastore.java:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.store;
2 |
3 | public class Datastore {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-generator/src/docs/showcase/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidmoten/xsd-forms/HEAD/xsd-forms-html-js/src/main/resources/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/xsd-scalaxb/src/main/java/com/github/davidmoten/xsdforms/Ignore.java:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms;
2 |
3 | /**
4 | * Exists solely to force generation of javadoc so maven release plugin doesnt' fail.
5 | **/
6 | public class Ignore {
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/timepicker.css:
--------------------------------------------------------------------------------
1 | /* css for timepicker */
2 | .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
3 | .ui-timepicker-div dl { text-align: left; }
4 | .ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
5 | .ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
6 | .ui-timepicker-div td { font-size: 90%; }
7 | .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/timepicker.css:
--------------------------------------------------------------------------------
1 | /* css for timepicker */
2 | .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
3 | .ui-timepicker-div dl { text-align: left; }
4 | .ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
5 | .ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
6 | .ui-timepicker-div td { font-size: 90%; }
7 | .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/configuration.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms
2 |
3 | case class Configuration(header: Option[String], footer: Option[String],
4 | extraImports: Option[String], extraScript: Option[String], extraCss: Option[String])
5 |
6 | case class Options(targetNamespace: String, idPrefix: Prefix)
7 |
8 | case class Prefix(value: String) {
9 | override def toString = value
10 | }
--------------------------------------------------------------------------------
/xsd-forms-maven-plugin-demo/src/test/java/com/github/davidmoten/xsdforms/maven/GeneratorMojoTest.java:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.maven;
2 |
3 | import static org.junit.Assert.assertTrue;
4 |
5 | import java.io.File;
6 |
7 | import org.junit.Test;
8 |
9 | public class GeneratorMojoTest {
10 |
11 | @Test
12 | public void testFilesWereGenerated() {
13 | assertTrue(new File("target/generated-resources/form.html").exists());
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "maven" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "daily"
12 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/scala/com/github/davidmoten/util/jsTest.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.util
2 |
3 | import org.junit.Test
4 | import org.junit.Assert.assertEquals
5 |
6 | @Test
7 | class JSTest {
8 |
9 | import org.junit.Assert._
10 |
11 | @Test
12 | def testJS {
13 | val js = JS()
14 | .line("function %s(doc,%s) {", "logit", "name")
15 | .line(" console.log(doc);")
16 | .line("}")
17 | println(js)
18 | val expected = """
19 | function logit(doc,name) {
20 | console.log(doc);
21 | }"""
22 | assertEquals(expected, js.toString)
23 | }
24 | }
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/util/js.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.util
2 |
3 | /**
4 | * Utility class for building javascript statements.
5 | */
6 | private[davidmoten] case class JS() {
7 | val b = new StringBuffer()
8 |
9 | def line: JS = line("")
10 |
11 | def line(s: String, params: Object*): JS = {
12 | b append "\n"
13 | b append String.format(s, params: _*)
14 | this
15 | }
16 |
17 | def append(s: String, params: Object*): JS = {
18 | b append String.format(s, params: _*)
19 | this
20 | }
21 |
22 | override def toString = b.toString
23 | }
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/resources/test-pattern-1.xsd:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/file-list-maven-plugin/src/test/java/com/github/davidmoten/xsdforms/maven/FileListerTest.java:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.maven;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import java.io.File;
6 |
7 | import org.junit.Test;
8 |
9 | public class FileListerTest {
10 |
11 | @Test
12 | public void testWithPrefix() {
13 | String s = FileLister.listFiles("boo", new File("src/test/resources"));
14 | System.out.println(s);
15 | assertEquals("boo/a\nboo/b\nboo/c/d\nboo/c/e/g\nboo/c/e/h",s);
16 | }
17 |
18 | @Test
19 | public void testWithoutPrefix() {
20 | String s = FileLister.listFiles("", new File("src/test/resources"));
21 | System.out.println(s);
22 | assertEquals("a\nb\nc/d\nc/e/g\nc/e/h",s);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/xsd-forms-generator-webapp/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Generator
7 | com.github.davidmoten.xsdforms.servlet.GeneratorServlet
8 |
9 |
10 |
11 | Generator
12 | /generate
13 |
14 |
15 |
16 | index.jsp
17 | index.html
18 |
19 |
20 |
21 | 30
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/scala/com/github/davidmoten/xsdforms/tree/treeUtilTest.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | import org.junit.Test
4 | import TreeUtil.parseMakeVisibleMap
5 | import org.junit.Assert.assertEquals
6 | import org.junit.Assert.assertTrue
7 | import org.junit.Assert.fail
8 |
9 | @Test
10 | class TreeUtilTest {
11 | import org.junit.Assert._
12 |
13 | import TreeUtil._
14 |
15 | @Test
16 | def testParseSingle {
17 | assertEquals(
18 | Map("true" -> 1),
19 | parseMakeVisibleMap(Some("true->1")))
20 | }
21 |
22 | @Test
23 | def testParseThree {
24 | assertEquals(
25 | Map("true" -> 1, "yes" -> 2, "boo" -> 3),
26 | parseMakeVisibleMap(Some("true->1,yes->2,boo->3")))
27 | }
28 |
29 | @Test
30 | def testParseNone {
31 | assertTrue(parseMakeVisibleMap(None).isEmpty)
32 | }
33 |
34 | @Test
35 | def testParseBlankReturnsEmptyMap {
36 | try {
37 | assertTrue(parseMakeVisibleMap(Some("")).isEmpty)
38 | fail
39 | } catch {
40 | case _: Throwable =>
41 | }
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/file-list-maven-plugin/src/main/java/com/github/davidmoten/xsdforms/maven/FileLister.java:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.maven;
2 |
3 | import java.io.File;
4 | import java.util.Arrays;
5 |
6 | public class FileLister {
7 |
8 | public static String listFiles(String prefix, File f) {
9 | String[] items = add(prefix, null, f).split("\n");
10 | Arrays.sort(items);
11 | StringBuilder s = new StringBuilder();
12 | for (String item : items) {
13 | if (s.length() > 0)
14 | s.append("\n");
15 | s.append(item);
16 | }
17 | return s.toString();
18 |
19 | }
20 |
21 | private static String add(String prefix, String path, File f) {
22 | StringBuilder s = new StringBuilder();
23 |
24 | String base;
25 | if (path == null)
26 | base = prefix;
27 | else if (path.length() == 0)
28 | base = f.getName();
29 | else
30 | base = path + "/" + f.getName();
31 | if (f.isDirectory())
32 | for (File file : f.listFiles()) {
33 | if (!file.getName().startsWith(".")) {
34 | if (s.length() > 0)
35 | s.append('\n');
36 | s.append(add(prefix, base, file));
37 | }
38 | }
39 | else if (!f.getName().startsWith("."))
40 | s.append(base);
41 | return s.toString();
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/util.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | import xsd._
4 |
5 | import javax.xml.namespace.QName
6 |
7 | import scalaxb._
8 |
9 | /**
10 | * ***************************************************************
11 | *
12 | * Util
13 | *
14 | *
15 | * **************************************************************
16 | */
17 |
18 | /**
19 | * Utility methods.
20 | *
21 | */
22 | private[xsdforms] object Util {
23 | def unexpected(s: String) = throw new RuntimeException(s)
24 | def unexpected = throw new RuntimeException
25 | }
26 |
27 | private[tree] case class XsdDatatype(name: String, pattern: Option[String] = None)
28 | case class XsdElement(name: String)
29 |
30 |
31 | /**
32 | * **************************************************************
33 | *
34 | * Instances
35 | *
36 | *
37 | * **************************************************************
38 | */
39 |
40 | private[xsdforms] case class Instances(heirarchy: Seq[Int] = List(), indentsDelta: Int = 0) {
41 | def add(instance: Int): Instances = Instances(heirarchy :+ instance, indentsDelta)
42 | def add(instance: Int, suppressIndent: Boolean) =
43 | Instances(heirarchy :+ instance, indentsDelta - (if (suppressIndent) 1 else 0))
44 | override def toString = heirarchy.mkString("_")
45 | def last = heirarchy.last
46 | def indentCount = heirarchy.size + indentsDelta
47 | }
48 |
49 |
50 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/scala/com/github/davidmoten/xsdforms/tstUtil.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms {
2 |
3 | import org.junit.Test
4 | import org.junit.Before
5 | import xsd.Schema
6 | import org.junit.runners.BlockJUnit4ClassRunner
7 | import org.junit.runner.notification.Failure
8 | import java.io.File
9 | import java.io.InputStream
10 | import tree._
11 |
12 | object TstUtil {
13 |
14 | import org.apache.commons.io._
15 |
16 | implicit val idPrefix = Prefix("c-")
17 |
18 | def generate(
19 | idPrefix: String,
20 | schemaInputStream: InputStream,
21 | rootElement: String,
22 | outputFile: File,
23 | extraScript: Option[String] = None) {
24 |
25 | //write results to a file
26 | outputFile.getParentFile().mkdirs
27 | val fos = new java.io.FileOutputStream(outputFile);
28 | Generator.generateHtml(schemaInputStream, fos, idPrefix, Some(rootElement))
29 | fos.close
30 | }
31 |
32 | def generateDemoForm(file: File) {
33 | println("generating demo form")
34 | generate(
35 | idPrefix = idPrefix.toString,
36 | schemaInputStream = TstUtil.getClass().getResourceAsStream("/demo.xsd"),
37 | rootElement = "main",
38 | outputFile = file)
39 | }
40 |
41 | def generateDemoForm {
42 | val file = new File("target/generated-webapp/demo-form.html")
43 | generateDemoForm(file)
44 | }
45 |
46 | def copyHtmlJs() {
47 | val directory = new File("target/generated-webapp")
48 | FileUtils.deleteDirectory(new File(directory, "css"))
49 | FileUtils.deleteDirectory(new File(directory, "js"))
50 | FileUtils.copyDirectory(new File("../xsd-forms-html-js/src/main/resources"), directory)
51 | }
52 |
53 | }
54 | }
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/presentation/css.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.presentation
2 |
3 | private[xsdforms] object Css {
4 | val ClassInvisible = "invisible"
5 | val ClassSequence = "sequence"
6 | val ClassSequenceLabel = "sequence-label"
7 | val ClassSequenceContent = "sequence-content"
8 | val ClassFieldset = "fieldset"
9 | val ClassChoiceLabel = "choice-label"
10 | val ClassDivChoiceItem = "div-choice-item"
11 | val ClassItemNumber = "item-number"
12 | val ClassItemTitle = "item-title"
13 | val ClassItemLabel = "item-label"
14 | val ClassItemInput = "item-input"
15 | val ClassItemHelp = "item-help"
16 | val ClassItemBefore = "item-before"
17 | val ClassItemAfter = "item-after"
18 | val ClassItemPath = "item-path"
19 | val ClassItemEnclosing = "item-enclosing"
20 | val ClassItemError = "item-error"
21 | val ClassChoiceItem = "choice-item"
22 | val ClassNonRepeatingTitle = "non-repeating-title"
23 | val ClassRepeatButton = "repeat-button"
24 | val ClassRemoveButton = "remove-button"
25 | val ClassRemoveButtonContainer = "remove-button-container"
26 | val ClassRepeatingEnclosing = "repeating-enclosing"
27 | val ClassItemInputTextarea = "item-input-textarea"
28 | val ClassItemInputText = "item-input-text"
29 | val ClassSelect = "select"
30 | val ClassChoice = "choice"
31 | val ClassWhite = "white"
32 | val ClassSmall = "small"
33 | val ClassClear = "clr"
34 | val ClassItemDescription = "item-description"
35 | val ClassTimePicker = "timepickerclass"
36 | val ClassDatePicker = "datepickerclass"
37 | val ClassDateTimePicker = "datetimepickerclass"
38 | val ClassMinOccursZero = "min-occurs-zero"
39 | val ClassMinOccursZeroContainer = "min-occurs-zero-container"
40 | val ClassMinOccursZeroLabel = "min-occurs-zero-label"
41 | }
42 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/node.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | import scala.collection.mutable.MutableList
4 | import javax.xml.namespace.QName
5 | import xsd._
6 |
7 | //every element is either a sequence, choice or simpleType
8 | // simpleTypes may be based on string, decimal, boolean, date, datetime
9 | // and may be restricted to a regex pattern, have min, max ranges
10 | // or be an enumeration. all elements may have minOccurs and maxOccurs
11 | //attributes.
12 |
13 | private[tree] case class Sequence(group: ExplicitGroupable)
14 | private[tree] case class Choice(group: ExplicitGroupable)
15 | private[tree] case class BaseType(qName: QName)
16 |
17 | private[tree] sealed trait Node {
18 | val element: ElementWrapper
19 | def isAnonymous = element.name.isEmpty
20 | }
21 |
22 | private[tree] sealed trait NodeGroup extends Node {
23 | val children: MutableList[Node] = MutableList()
24 | }
25 |
26 | // immutable would be preferrable but should be safe because not changed after tree created
27 | private[tree] sealed trait NodeBasic extends Node
28 |
29 | private[tree] sealed trait BasicType
30 | private[tree] case class BasicTypeSimple(typ: SimpleType) extends BasicType
31 | private[tree] case class BasicTypeBase(typ: BaseType) extends BasicType
32 |
33 | //TODO stop using mutable types
34 | private[tree] case class NodeSequence(element: ElementWrapper,
35 | override val children: MutableList[Node]) extends NodeGroup
36 | private[tree] case class NodeChoice(element: ElementWrapper, choice: Choice,
37 | override val children: MutableList[Node]) extends NodeGroup
38 | private[tree] case class NodeSimpleType(element: ElementWrapper, typ: SimpleType) extends NodeBasic
39 | private[tree] case class NodeBaseType(element: ElementWrapper, typ: BaseType) extends NodeBasic
40 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/resources/annotations-demo.xsd:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | 'header' here
10 | ]]>
11 |
12 |
13 | 'footer' here.
15 | ]]>
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
29 |
30 |
31 |
32 |
33 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | ## Does continuous integration build with Java 8 and 11 and
4 | ## if succeeds and due to a dependabot pull request (minor or
5 | ## patch verson change) it will automatically merge the PR.
6 |
7 | ## Unlike many sample automerge workflows this does not rely
8 | ## on third-party libraries apart from the official dependabot
9 | ## repository ones. This reduces the security risk significantly
10 | ## (we don't want to unknowingly merge malicious code or expose
11 | ## secrets to a malicious third party).
12 |
13 | on: [push, pull_request]
14 |
15 | jobs:
16 | build:
17 | runs-on: ubuntu-latest
18 | strategy:
19 | matrix:
20 | java: ['8']
21 | steps:
22 | - uses: actions/checkout@v4
23 | - name: Set up JDK ${{ matrix.java }}
24 | uses: actions/setup-java@v4
25 | with:
26 | java-version: ${{ matrix.java }}
27 | distribution: 'temurin'
28 | - name: Build with Maven
29 | run: mvn --batch-mode --update-snapshots verify
30 | - uses: codecov/codecov-action@v4
31 | with:
32 | file: ./**/target/site/jacoco/jacoco.xml
33 | name: codecov
34 | dependabot:
35 | runs-on: ubuntu-latest
36 | needs: build
37 | permissions:
38 | pull-requests: write
39 | contents: write
40 | if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request' }}
41 | steps:
42 | - name: Dependabot metadata
43 | id: metadata
44 | uses: dependabot/fetch-metadata@v2.1.0
45 | with:
46 | github-token: "${{ secrets.GITHUB_TOKEN }}"
47 | - name: Enable auto-merge for Dependabot PRs
48 | if: ${{!contains(steps.metadata.outputs.dependency-names, 'maven-plugin-api') && (steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.update-type == 'version-update:semver-patch')}}
49 | run: gh pr merge --auto --rebase "$PR_URL"
50 | env:
51 | PR_URL: ${{github.event.pull_request.html_url}}
52 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
53 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/xsd-util.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | /**
4 | * Utility methods and constants for XML Schemas (XSD).
5 | */
6 | private[xsdforms] object XsdUtil {
7 |
8 | import scalaxb.DataRecord
9 | import javax.xml.namespace.QName
10 |
11 | val Xsd = "http://www.w3.org/2001/XMLSchema"
12 | val AppInfoSchema = "http://moten.david.org/xsd-forms"
13 |
14 | def toQName[T](d: DataRecord[T]) =
15 | new QName(d.namespace.getOrElse(null), d.key.getOrElse(null))
16 | def qn(namespaceUri: String, localPart: String) = new QName(namespaceUri, localPart)
17 | def qn(localPart: String): QName = new QName(Xsd, localPart)
18 | def qn(datatype: XsdDatatype): QName = qn(Xsd, datatype.name)
19 |
20 | val QnXsdExtension = qn("extension")
21 | val QnXsdSequence = qn("sequence")
22 | val QnXsdChoice = qn("choice")
23 | val QnXsdAppInfo = qn("appinfo")
24 | val QnXsdElement = qn("element")
25 |
26 | //TODO use enumeration
27 | val XsdDateTime = XsdDatatype("dateTime")
28 | val XsdDate = XsdDatatype("date")
29 | val XsdTime = XsdDatatype("time")
30 | val XsdInteger = XsdDatatype("integer", Some("\\d+"))
31 | val XsdInt = XsdDatatype("int", Some("-?\\d+"))
32 | val XsdLong = XsdDatatype("long", Some("-?\\d+"))
33 | val XsdShort = XsdDatatype("short", Some("-?\\d+"))
34 | val XsdPositiveInteger = XsdDatatype("positiveInteger", Some("[1-9]\\d*"))
35 | val XsdNegativeInteger = XsdDatatype("negativeInteger", Some("-[1-9]\\d*"))
36 |
37 | //TODO allow zero for non-positive integer (adjust regex)
38 | val XsdNonPositiveInteger = XsdDatatype("nonPositiveInteger", Some("(-\\d+)|0"))
39 | val XsdNonNegativeInteger = XsdDatatype("nonNegativeInteger", Some("\\d+"))
40 | val XsdDecimal = XsdDatatype("decimal", Some("-?\\d+(\\.\\d*)?"))
41 | val XsdBoolean = XsdDatatype("boolean")
42 | val XsdString = XsdDatatype("string")
43 | val XsdDouble = XsdDatatype("double", Some("-?\\d(\\.\\d*)?([eE]-?\\d+)?"))
44 | val XsdFloat = XsdDatatype("float", Some("-?\\d(\\.\\d*)?([eE]-?\\d+)?"))
45 | val XsdAttribute = XsdDatatype("attribute", None)
46 | val XsdAnnotation = XsdDatatype("annotation", None)
47 | }
--------------------------------------------------------------------------------
/file-list-maven-plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.github.davidmoten.xsdforms
6 | xsd-forms
7 | 0.2.2-SNAPSHOT
8 |
9 | file-list-maven-plugin
10 | ${project.artifactId}
11 | maven-plugin
12 |
13 | UTF-8
14 |
15 |
16 |
17 | org.apache.maven
18 | maven-plugin-api
19 | 3.6.0
20 | provided
21 |
22 |
23 | org.apache.maven.plugin-tools
24 | maven-plugin-annotations
25 | 3.9.0
26 | provided
27 |
28 |
29 | org.codehaus.plexus
30 | plexus-utils
31 | 3.5.1
32 |
33 |
34 | junit
35 | junit
36 | 4.13.2
37 | test
38 |
39 |
40 |
41 |
42 |
43 | org.apache.maven.plugins
44 | maven-plugin-plugin
45 | 3.9.0
46 |
47 | file-list
48 | true
49 |
50 |
51 |
52 | mojo-descriptor
53 |
54 | descriptor
55 |
56 |
57 |
58 | help-goal
59 |
60 | helpmojo
61 |
62 |
63 |
64 |
65 |
66 | org.apache.maven.plugins
67 | maven-compiler-plugin
68 |
69 | 1.8
70 | 1.8
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/form-creator-util.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | private[tree] object TreeUtil {
4 | import xsd.Annotatedable
5 | import XsdUtil.AppInfoSchema
6 |
7 | def parseMakeVisibleMap(value: Option[String]): Map[String, Int] = {
8 | import Util._
9 |
10 | val Problem = "could not parse makeVisible, expecting 'value1->1,value2->2' (pairs delimited by comma and key value delimited by '->'"
11 | value match {
12 | case Some(s) =>
13 | s.split(",")
14 | .toList
15 | .map(
16 | x => {
17 | val items = x.split("->")
18 | if (items.length < 2)
19 | unexpected(Problem)
20 | (items(0), items(1).toInt)
21 | }).toMap
22 | case None => Map()
23 | }
24 | }
25 |
26 | }
27 |
28 | private[tree] case class ElementWithNumber(element: ElementWrapper, number: Int)
29 |
30 | //Use Vector because has O(1) append
31 | private[tree] case class HtmlJs(html: Vector[String], js: Vector[String]) {
32 | def addHtml(html2: String) = HtmlJs(html.+:(html2), js)
33 | def addJs(js2: String) = HtmlJs(html, js.+:(js2))
34 | }
35 |
36 | private class ElementNumbersAssigner(node: Node) {
37 |
38 | private def assign(node: Node, number: Int): Map[ElementWrapper, Int] = {
39 | val m = Map(node.element -> (number + 1))
40 | node match {
41 | case n: NodeGroup =>
42 | n.children.foldLeft(m)(
43 | (map, nd) => map ++ assign(nd, number + map.size))
44 | case _ =>
45 | m
46 | }
47 | }
48 |
49 | val assignments = assign(node, 0)
50 |
51 | }
52 |
53 | private[tree] trait FormCreatorState {
54 | import com.github.davidmoten.xsdforms.tree.html.Html
55 | import com.github.davidmoten.xsdforms.Options
56 |
57 | val options: Options
58 |
59 | val tree: Node
60 |
61 | implicit val idPrefix = options.idPrefix
62 |
63 | val html: Html
64 |
65 | //assign element numbers so that order of display on page
66 | //will match order of element numbers. To do this must
67 | //traverse children left to right before siblings
68 | private val elementNumbers = new ElementNumbersAssigner(tree).assignments
69 |
70 | implicit def toElementWithNumber(element: ElementWrapper): ElementWithNumber =
71 | ElementWithNumber(element, elementNumber(element))
72 |
73 | private def elementNumber(e: ElementWrapper): Int =
74 | elementNumbers.get(e).get;
75 | }
76 |
77 |
78 |
--------------------------------------------------------------------------------
/demo-scalaxb/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.github.davidmoten.xsdforms
5 | xsd-forms
6 | 0.2.2-SNAPSHOT
7 |
8 | demo-scalaxb
9 | ${project.artifactId}
10 |
11 |
12 |
13 | org.apache.maven.plugins
14 | maven-deploy-plugin
15 | 3.1.1
16 |
17 | true
18 |
19 |
20 |
21 |
22 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/file-list-maven-plugin/src/main/java/com/github/davidmoten/xsdforms/maven/FileListMojo.java:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.maven;
2 |
3 | /*
4 | * Copyright 2001-2005 The Apache Software Foundation.
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 | * http://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 | import java.io.File;
20 | import java.io.FileOutputStream;
21 | import java.io.IOException;
22 | import java.nio.charset.Charset;
23 |
24 | import org.apache.maven.plugin.AbstractMojo;
25 | import org.apache.maven.plugin.MojoExecutionException;
26 | import org.apache.maven.plugins.annotations.LifecyclePhase;
27 | import org.apache.maven.plugins.annotations.Mojo;
28 | import org.apache.maven.plugins.annotations.Parameter;
29 |
30 | /**
31 | * Goal which generates file list.
32 | *
33 | */
34 | @Mojo(name = "list", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, threadSafe = true)
35 | public class FileListMojo extends AbstractMojo {
36 | /**
37 | * The file to contain the file list.
38 | *
39 | */
40 | @Parameter(property = "output", defaultValue = "${project.build.directory}/generated-resources/file-list.txt")
41 | private File output;
42 |
43 | /**
44 | * The directory to list.
45 | *
46 | */
47 | @Parameter(property = "directory", defaultValue = "${basedir}/src/main/resources")
48 | private File directory;
49 |
50 | @Parameter(property = "prefix", defaultValue = "")
51 | private String prefix;
52 |
53 | @Override
54 | public void execute() throws MojoExecutionException {
55 | if (prefix == null)
56 | prefix = "";
57 | getLog().info(
58 | "writing list of " + directory + " to " + output
59 | + " with prefix " + prefix);
60 | String list = FileLister.listFiles(prefix, directory);
61 | getLog().info("list=\n"+list);
62 | output.getParentFile().mkdirs();
63 | try {
64 | FileOutputStream fos = new FileOutputStream(output);
65 | fos.write(list.getBytes(Charset.forName("UTF-8")));
66 | fos.close();
67 | } catch (IOException e) {
68 | throw new MojoExecutionException(e.getMessage(), e);
69 | }
70 | getLog().info("written to " + output);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/xsd-forms-maven-plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.github.davidmoten.xsdforms
6 | xsd-forms
7 | 0.2.2-SNAPSHOT
8 |
9 | xsd-forms-maven-plugin
10 | ${project.artifactId}
11 | maven-plugin
12 |
13 | UTF-8
14 |
15 |
16 |
17 | org.apache.maven
18 | maven-plugin-api
19 | 3.6.0
20 | provided
21 |
22 |
23 | org.apache.maven.plugin-tools
24 | maven-plugin-annotations
25 | 3.9.0
26 | provided
27 |
28 |
29 | org.codehaus.plexus
30 | plexus-utils
31 | 3.5.1
32 |
33 |
34 | junit
35 | junit
36 | 4.13.2
37 | test
38 |
39 |
40 | ${project.parent.groupId}
41 | xsd-forms-generator
42 | ${project.parent.version}
43 |
44 |
45 |
46 |
47 |
48 | org.apache.maven.plugins
49 | maven-plugin-plugin
50 | 3.9.0
51 |
52 | xsd-forms
53 | true
54 |
55 |
56 |
57 | mojo-descriptor
58 |
59 | descriptor
60 |
61 |
62 |
63 | help-goal
64 |
65 | helpmojo
66 |
67 |
68 |
69 |
70 |
71 | org.apache.maven.plugins
72 | maven-compiler-plugin
73 |
74 | 1.8
75 | 1.8
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/xsd-forms-generator-webapp/src/main/java/com/github/davidmoten/xsdforms/servlet/GeneratorServlet.java:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.servlet;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 |
7 | import javax.servlet.ServletException;
8 | import javax.servlet.http.HttpServlet;
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 |
12 | import scala.Option;
13 |
14 | import com.github.davidmoten.xsdforms.Generator;
15 |
16 | public class GeneratorServlet extends HttpServlet {
17 |
18 | private static final long serialVersionUID = -1329200353122439077L;
19 | private static final String PARAMETER_ROOT_ELEMENT = "rootElement";
20 | private static final String PARAMETER_ID_PREFIX = "idPrefix";
21 | private static final String ACTION_ZIP = "zip";
22 |
23 | @Override
24 | protected void doPost(HttpServletRequest req, HttpServletResponse resp)
25 | throws ServletException, IOException {
26 | String schema = req.getParameter("schema");
27 | InputStream schemaIn = new ByteArrayInputStream(schema.getBytes());
28 | String idPrefix = nullToBlank(req.getParameter(PARAMETER_ID_PREFIX));
29 | String rootElementParam = blankToNull(req.getParameter(PARAMETER_ROOT_ELEMENT));
30 | Option rootElement = Option.apply(rootElementParam);
31 |
32 | String action = req.getParameter("action");
33 | if (ACTION_ZIP.equals(action)) {
34 | returnZip(resp, schemaIn, idPrefix, rootElement);
35 | } else {
36 | returnHtml(resp, schemaIn, idPrefix, rootElement);
37 | }
38 | }
39 |
40 | private void returnZip(HttpServletResponse resp, InputStream schemaIn,
41 | String idPrefix, Option rootElement) throws IOException {
42 | resp.setContentType("application/zip");
43 | resp.setHeader("Content-Disposition",
44 | "attachment; filename=site.zip");
45 | Generator.generateZip(schemaIn, resp.getOutputStream(), idPrefix,
46 | rootElement);
47 | }
48 |
49 |
50 | private void returnHtml(HttpServletResponse resp, InputStream schemaIn,
51 | String idPrefix, Option rootElement) throws IOException {
52 | resp.setContentType("text/html");
53 | Generator.generateHtml(schemaIn, resp.getOutputStream(), idPrefix,
54 | rootElement);
55 | }
56 |
57 | @Override
58 | protected void doGet(HttpServletRequest req, HttpServletResponse resp)
59 | throws ServletException, IOException {
60 | doPost(req,resp);
61 | }
62 |
63 | private static String blankToNull(String s) {
64 | if (s != null && s.trim().length() == 0)
65 | return null;
66 | else
67 | return s;
68 | }
69 |
70 | private static String nullToBlank(String s) {
71 | if (s == null)
72 | return "";
73 | else
74 | return s;
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/ids.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | private[xsdforms] object Ids {
4 |
5 | import com.github.davidmoten.xsdforms.{Prefix}
6 |
7 | val InstanceDelimiter = "-instance-"
8 | val ChoiceIndexDelimiter = "-choice-"
9 |
10 | def getItemId(number: Int, instances: Instances)(implicit idPrefix: Prefix) =
11 | idPrefix + "item-" + number + InstanceDelimiter + instances
12 |
13 | def getItemName(number: Int, instances: Instances)(implicit idPrefix: Prefix): String =
14 | idPrefix + "item-input-" + number + InstanceDelimiter + instances;
15 |
16 | def getItemErrorId(number: Int, instances: Instances)(implicit idPrefix: Prefix): String =
17 | idPrefix + "item-error-" + number + InstanceDelimiter + instances
18 |
19 | def getChoiceItemId(number: Int, index: Int,
20 | instances: Instances)(implicit idPrefix: Prefix): String =
21 | getItemId(number, instances)(idPrefix) + ChoiceIndexDelimiter + index
22 |
23 | def getChoiceItemName(number: Int, instances: Instances)(implicit idPrefix: Prefix): String =
24 | idPrefix + "item-input-" + number + InstanceDelimiter + instances
25 |
26 | def choiceContentId(number: Int, index: Int,
27 | instances: Instances)(implicit idPrefix: Prefix): String =
28 | idPrefix + "choice-content-" + number + InstanceDelimiter +
29 | instances + ChoiceIndexDelimiter + index
30 |
31 | def getItemId(number: Int, enumeration: Integer,
32 | instances: Instances)(implicit idPrefix: Prefix): String =
33 | getItemId(number, instances) + "-" + enumeration
34 |
35 | def getRepeatButtonId(number: Int, instances: Instances)(implicit idPrefix: Prefix): String =
36 | idPrefix + "repeat-button-" + number + InstanceDelimiter + instances
37 |
38 | def getRemoveButtonId(number: Int, instances: Instances)(implicit idPrefix: Prefix): String =
39 | idPrefix + "remove-button-" + number + InstanceDelimiter + instances
40 |
41 | def getRepeatingEnclosingId(number: Int,
42 | instances: Instances)(implicit idPrefix: Prefix): String =
43 | idPrefix + "repeating-enclosing-" + number + InstanceDelimiter + instances
44 |
45 | def getMinOccursZeroId(number: Int, instances: Instances)(implicit idPrefix: Prefix): String =
46 | idPrefix + "min-occurs-zero-" + number + InstanceDelimiter + instances
47 |
48 | def getMinOccursZeroName(number: Int,
49 | instances: Instances)(implicit idPrefix: Prefix): String =
50 | idPrefix + "min-occurs-zero-name" + number + InstanceDelimiter + instances
51 |
52 | def getItemEnclosingId(number: Int, instances: Instances)(implicit idPrefix: Prefix) =
53 | idPrefix + "item-enclosing-" + number + InstanceDelimiter + instances
54 |
55 | def getPathId(number: Int, instances: Instances)(implicit idPrefix: Prefix) =
56 | idPrefix + "item-path-" + number + InstanceDelimiter + instances
57 | }
--------------------------------------------------------------------------------
/xsd-forms-maven-plugin-demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.github.davidmoten.xsdforms
5 | xsd-forms
6 | 0.2.2-SNAPSHOT
7 |
8 | xsd-forms-maven-plugin-demo
9 | ${project.artifactId}
10 | jar
11 |
12 |
13 |
14 | junit
15 | junit
16 | 4.13.2
17 | test
18 |
19 |
20 |
21 |
22 |
23 | ${project.parent.groupId}
24 | xsd-forms-maven-plugin
25 | ${project.parent.version}
26 |
27 |
28 |
29 | ${project.parent.groupId}
30 | demo-scalaxb
31 | ${project.parent.version}
32 |
33 |
34 |
35 |
36 |
37 | generate
38 |
39 |
40 |
41 |
42 |
43 | /demo.xsd
44 |
45 | a-
46 |
47 | main
48 |
49 | ${project.build.directory}/generated-resources
50 |
51 |
52 |
53 | org.codehaus.mojo
54 | build-helper-maven-plugin
55 | 3.3.0
56 |
57 |
58 | add-resource
59 | generate-resources
60 |
61 | add-resource
62 |
63 |
64 |
65 |
66 | ${project.build.directory}/generated-resources
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | org.apache.maven.plugins
75 | maven-deploy-plugin
76 | 3.1.1
77 |
78 | true
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/xsd-forms-maven-plugin/src/main/java/com/github/davidmoten/xsdforms/maven/GenerateMojo.java:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.maven;
2 |
3 | /*
4 | * Copyright 2001-2005 The Apache Software Foundation.
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 | * http://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 | import java.io.File;
20 | import java.io.FileInputStream;
21 | import java.io.FileNotFoundException;
22 | import java.io.InputStream;
23 |
24 | import org.apache.maven.plugin.AbstractMojo;
25 | import org.apache.maven.plugin.MojoExecutionException;
26 | import org.apache.maven.plugins.annotations.LifecyclePhase;
27 | import org.apache.maven.plugins.annotations.Mojo;
28 | import org.apache.maven.plugins.annotations.Parameter;
29 |
30 | import scala.Option;
31 |
32 | import com.github.davidmoten.xsdforms.Generator;
33 |
34 | /**
35 | * Goal which generates form and dependent files.
36 | *
37 | */
38 | @Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, threadSafe = true)
39 | public class GenerateMojo extends AbstractMojo {
40 | /**
41 | * The directory to write the files to.
42 | *
43 | */
44 | @Parameter(property = "xsdforms.output.directory", defaultValue = "${project.build.directory}/generated-resources")
45 | private File outputDirectory;
46 |
47 | /**
48 | * The schema path (on classpath or as file)
49 | *
50 | */
51 | @Parameter(property = "xsdforms.schema", required = true)
52 | private String schema;
53 |
54 | /**
55 | * The id prefix in generated html.
56 | *
57 | */
58 | @Parameter(property = "xsdforms.id.prefix")
59 | private String idPrefix;
60 |
61 | /**
62 | * Top level element from schema to use as root level element in xml.
63 | *
64 | */
65 | @Parameter(property = "xsdforms.root.element")
66 | private String rootElement;
67 |
68 | @Override
69 | public void execute() throws MojoExecutionException {
70 |
71 | if (schema == null)
72 | throw new MojoExecutionException("schema must be specified");
73 | // look first on classpath
74 | InputStream schemaIn = getInputStreamFromClasspathOrFile(schema);
75 |
76 | Generator.generateDirectory(schemaIn, outputDirectory, idPrefix,
77 | Option.apply(rootElement));
78 | }
79 |
80 | private static InputStream getInputStreamFromClasspathOrFile(String path)
81 | throws MojoExecutionException {
82 |
83 | InputStream in = GenerateMojo.class.getResourceAsStream(path);
84 | // then on file system
85 | if (in == null)
86 | try {
87 | in = new FileInputStream(path);
88 | } catch (FileNotFoundException e) {
89 | throw new MojoExecutionException(e.getMessage() + " path="
90 | + path, e);
91 | }
92 | return in;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/xsd-scalaxb/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.github.davidmoten.xsdforms
5 | xsd-forms
6 | 0.2.2-SNAPSHOT
7 |
8 | xsd-scalaxb
9 | ${project.artifactId}
10 |
11 |
12 |
13 | net.alchim31.maven
14 | scala-maven-plugin
15 | ${scala.plugin.version}
16 |
17 |
18 |
19 | compile
20 | testCompile
21 |
22 |
23 |
24 | -Xms64m
25 | -Xmx1024m
26 | -XX:MaxPermSize=256m
27 |
28 |
29 |
30 | -dependencyfile
31 | ${project.build.directory}/.scala_dependencies
32 |
33 |
34 |
35 |
36 |
37 |
38 | org.scalaxb
39 | scalaxb-maven-plugin
40 | ${scalaxb.plugin.version}
41 |
42 | xsd
43 | ${basedir}/src/main/xsd
44 |
45 |
46 |
47 | scalaxb
48 |
49 | generate
50 |
51 |
52 |
53 |
54 |
55 | org.apache.maven.plugins
56 | maven-source-plugin
57 | 3.3.0
58 |
59 |
60 | attach-sources
61 |
62 | jar
63 |
64 |
65 |
66 |
67 |
68 | org.codehaus.mojo
69 | build-helper-maven-plugin
70 | 3.3.0
71 |
72 |
73 | add-source
74 | generate-sources
75 |
76 | add-source
77 |
78 |
79 |
80 | ${project.build.directory}/generated-sources/scalaxb
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/xsd-scalaxb/src/main/xsd/xsd-forms.xsd:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/resources/simple.xsd:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
23 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/visitor.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | import com.github.davidmoten.xsdforms.Configuration
4 |
5 | /**
6 | * **************************************************************
7 | *
8 | * Visitor
9 | *
10 | *
11 | * **************************************************************
12 | */
13 |
14 | private[xsdforms] trait Visitor {
15 | import xsd._
16 |
17 | def configuration(configuration: Configuration)
18 | def startSequence(e: Element)
19 | def endSequence
20 | def startChoice(e: Element, choice: Choice)
21 | def startChoiceItem(e: Element, p: ParticleOption, index: Int)
22 | def endChoiceItem
23 | def endChoice
24 | def simpleType(e: Element, typ: SimpleType)
25 | def baseType(e: Element, typ: BaseType)
26 | }
27 |
28 | /**
29 | * **************************************************************
30 | *
31 | * TreeCreatingVisitor
32 | *
33 | *
34 | * **************************************************************
35 | */
36 |
37 | private[xsdforms] class TreeCreatingVisitor extends Visitor {
38 | import xsd._
39 | import Util._
40 |
41 | private var tree: Option[Node] = None
42 | var configuration: Option[Configuration] = None
43 | private val stack = new scala.collection.mutable.Stack[Node]
44 |
45 | import scala.collection.mutable.MutableList
46 | import scala.collection.mutable.HashMap
47 |
48 | private val nodes = new HashMap[Element, Node]()
49 |
50 | private implicit def wrap(e: Element): ElementWrapper = ElementWrapper(e)
51 |
52 | override def configuration(config: Configuration) {
53 | configuration = Some(config)
54 | }
55 |
56 | override def startSequence(e: Element) {
57 | val seq = NodeSequence(e, MutableList())
58 | addChild(seq)
59 | stack.push(seq)
60 | nodes.put(e, seq)
61 | }
62 |
63 | /**
64 | * If tree is empty then sets tree to existing node. If not empty then adds node
65 | * to children of top of stack.
66 | *
67 | * @param node
68 | */
69 | private def addChild(node: Node) {
70 | if (tree.isEmpty) tree = Some(node);
71 | else
72 | stack.top match {
73 | case g: NodeGroup => g.children += node
74 | case _ => unexpected
75 | }
76 | }
77 |
78 | override def endSequence {
79 | stack.pop
80 | }
81 |
82 | override def startChoice(e: Element, choice: Choice) {
83 | val chc = NodeChoice(e, choice, MutableList())
84 | addChild(chc)
85 | stack.push(chc)
86 | nodes.put(e, chc)
87 | }
88 |
89 | override def startChoiceItem(e: Element, p: ParticleOption, index: Int) {
90 | // do nothing
91 | }
92 |
93 | override def endChoiceItem {
94 | //do nothing
95 | }
96 |
97 | override def endChoice {
98 | stack.pop
99 | }
100 |
101 | override def simpleType(e: Element, typ: SimpleType) {
102 | val s = NodeSimpleType(e, typ)
103 | addChild(s)
104 | nodes.put(e, s)
105 | }
106 |
107 | override def baseType(e: Element, typ: BaseType) {
108 | val s = NodeBaseType(e, typ)
109 | addChild(s)
110 | }
111 |
112 | private def toString(node: Node, margin: String): String = {
113 | node match {
114 | case NodeBaseType(e, typ) => margin + "NodeBaseType=" + e.name.get
115 | case NodeSimpleType(e, typ) => margin + "NodeSimpleType=" + e.name.get
116 | case n: NodeGroup => margin + n.getClass.getSimpleName + "=\n" +
117 | n.children.map(c => toString(c, margin + " ")).mkString("\n")
118 | case _ => unexpected
119 | }
120 | }
121 |
122 | override def toString: String = {
123 | if (tree.isEmpty)
124 | ""
125 | else
126 | toString(tree.get, "")
127 | }
128 |
129 | def rootNode: Node = tree.get;
130 |
131 | }
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/scala/com/github/davidmoten/xsdforms/generatorTest.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms {
2 |
3 | import org.junit.Test
4 | import org.junit.Before
5 | import xsd.Schema
6 | import org.junit.runners.BlockJUnit4ClassRunner
7 | import org.junit.runner.notification.Failure
8 | import java.io.File
9 | import java.io.InputStream
10 | import tree._
11 |
12 | @Test
13 | class GeneratorTest {
14 |
15 | import org.apache.commons.io._
16 |
17 | import TstUtil._
18 |
19 | import java.io._
20 |
21 | import org.junit.Assert._
22 |
23 | @Before
24 | def testSetupWebapp() {
25 | copyHtmlJs
26 | }
27 |
28 | @Test
29 | def generatePersonForm() {
30 | println("generating person form")
31 | generate(
32 | idPrefix = "a-",
33 | schemaInputStream = TstUtil.getClass().getResourceAsStream("/test.xsd"),
34 | rootElement = "person",
35 | outputFile = new File("target/generated-webapp/person-form.html"))
36 | }
37 |
38 | @Test
39 | def generateSimpleForm() {
40 | println("generating simple form")
41 | generate(
42 | idPrefix = "a-",
43 | schemaInputStream = TstUtil.getClass().getResourceAsStream("/simple.xsd"),
44 | rootElement = "person",
45 | outputFile = new File("target/generated-webapp/simple-form.html"))
46 | }
47 |
48 | @Test
49 | def generateCensusForm {
50 | println("generating census form")
51 | generate(
52 | idPrefix = "b-",
53 | schemaInputStream = TstUtil.getClass().getResourceAsStream("/australian-census-2011.xsd"),
54 | rootElement = "census",
55 | outputFile = new File("target/generated-webapp/census-form.html"))
56 | }
57 |
58 | @Test
59 | def generatePolrepForm {
60 | println("generating polrep form")
61 | generate(
62 | idPrefix = "b-",
63 | schemaInputStream = TstUtil.getClass().getResourceAsStream("/polrep.xsd"),
64 | rootElement = "polrep",
65 | outputFile = new File("target/generated-webapp/polrep-form.html"))
66 | }
67 |
68 | @Test
69 | def generateTheAnnotationsDemoForm {
70 | println("generating the annotations demo form")
71 | generate(
72 | idPrefix = "b-",
73 | schemaInputStream = TstUtil.getClass().getResourceAsStream("/annotations-demo.xsd"),
74 | rootElement = "person",
75 | outputFile = new File("target/generated-webapp/annotations-demo.html"))
76 | }
77 |
78 | @Test
79 | def generateTheDemoForm {
80 | println("generating the demo form")
81 | generate(
82 | idPrefix = "b-",
83 | schemaInputStream = TstUtil.getClass().getResourceAsStream("/demo.xsd"),
84 | rootElement = "main",
85 | outputFile = new File("target/generated-webapp/demo-form.html"))
86 | }
87 |
88 | @Test
89 | def testGenerateZip() {
90 | val out = new File("target/out.zip")
91 | new FileOutputStream(out)
92 | Generator.generateZip(getClass.getResourceAsStream("/demo.xsd"), new FileOutputStream(out))
93 | assertTrue(out.exists)
94 |
95 | import java.util.zip._
96 | val zipFile = new ZipFile(out)
97 |
98 | import scala.collection.JavaConversions._
99 | val names = enumerationAsScalaIterator(zipFile.entries()).map(_.getName).toSet
100 | println(names.mkString("\n"))
101 | assertTrue(names.contains("form.html"))
102 | assertTrue(names.contains("css/xsd-forms-style.css"))
103 | assertTrue(names.contains("js/xsd-forms-override.js"))
104 |
105 | Option.empty
106 | }
107 |
108 | @Test
109 | def testGenerateDirectory() {
110 | val out = new File("target/out.zip")
111 | val directory = new File("target/testGenerateDirectory")
112 | Generator.generateDirectory(getClass.getResourceAsStream("/demo.xsd"), directory)
113 | assertTrue(directory.exists)
114 | Option.empty
115 | }
116 |
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/xsd-scalaxb/src/main/xsd/miuml-class.xsd:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
14 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
53 |
54 |
55 |
56 |
57 |
58 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/generator.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms
2 |
3 | /**
4 | * Generates html and javascript based web forms on XML Schema (XSD).
5 | */
6 | object `package` {}
7 |
8 | /**
9 | * Generates html and javascript based on XML schema (XSD).
10 | */
11 | object Generator {
12 | import java.io._
13 | import java.util.UUID
14 | import java.util.zip._
15 | import org.apache.commons.io._
16 | import xsd._
17 | import tree._
18 |
19 | /**
20 | * Using the given xml schema generates html and js files and copies
21 | * static js and css into a zipped file that is written to the given
22 | * OutputStream. The result is a standalone site for the form.
23 | *
24 | * @param schema
25 | * @param zip
26 | * @param idPrefix
27 | * @param rootElement
28 | */
29 | def generateZip(
30 | schema: InputStream,
31 | zip: OutputStream,
32 | idPrefix: String = "a-",
33 | rootElement: Option[String] = None) {
34 |
35 | val zipOut = new ZipOutputStream(zip)
36 |
37 | def action(bytes: Array[Byte], name: String, isDirectory: Boolean) {
38 | zipOut putNextEntry new ZipEntry(name)
39 | zipOut write bytes
40 | }
41 |
42 | copyJsCssAndGeneratedForm(schema, action, idPrefix, rootElement)
43 |
44 | zipOut.close
45 | }
46 |
47 | /**
48 | * Using the given xml schema generates html and js files and copies
49 | * static js and css into the given directory. The result is a
50 | * standalone site for the form.
51 | *
52 | * @param schema
53 | * @param directory
54 | * @param idPrefix
55 | * @param rootElement
56 | */
57 | def generateDirectory(
58 | schema: InputStream,
59 | directory: File,
60 | idPrefix: String = "a-",
61 | rootElement: Option[String] = None) {
62 |
63 | def action(bytes: Array[Byte], name: String, isDirectory: Boolean) {
64 | import org.apache.commons.io.FileUtils
65 | val path = directory.getPath + File.separator + name
66 | val file = new File(path)
67 | new File(file.getParent).mkdirs
68 | if (isDirectory)
69 | file.mkdir
70 | else {
71 | val fos = new FileOutputStream(file)
72 | fos write bytes
73 | fos.close
74 | }
75 | }
76 |
77 | copyJsCssAndGeneratedForm(schema, action, idPrefix, rootElement)
78 | }
79 |
80 | private def copyJsCssAndGeneratedForm(
81 | schema: InputStream,
82 | action: (Array[Byte], String, Boolean) => Unit,
83 | idPrefix: String = "a-",
84 | rootElement: Option[String] = None) {
85 | val text = generateHtmlAsString(schema, idPrefix, rootElement)
86 |
87 | val list = io.Source.fromInputStream(getClass.getResourceAsStream("/file-list.txt"))
88 | list.getLines.foreach { path =>
89 | val bytes = IOUtils.toByteArray(getClass.getResourceAsStream("/" + path))
90 | action(bytes, path, false)
91 | }
92 |
93 | val name = "form.html"
94 | action(text.getBytes, name, false)
95 | }
96 |
97 | /**
98 | * Using the given xml schema generates html and js into a file that
99 | * is written to the given OutputStream.
100 | *
101 | * @param schema
102 | * @param html
103 | * @param idPrefix
104 | * @param rootElement
105 | */
106 | def generateHtml(schema: InputStream,
107 | html: OutputStream,
108 | idPrefix: String = "a-",
109 | rootElement: Option[String] = None) {
110 |
111 | val text = generateHtmlAsString(schema, idPrefix, rootElement)
112 | html write text.getBytes
113 | }
114 |
115 | /**
116 | * Returns the text of a file containing generated html and js based on
117 | * the given schema.
118 | *
119 | * @param schema
120 | * @param idPrefix
121 | * @param rootElement
122 | * @return html text including js
123 | */
124 | def generateHtmlAsString(schema: InputStream,
125 | idPrefix: String = "a-",
126 | rootElement: Option[String] = None): String = {
127 |
128 | import scala.xml._
129 |
130 | val schemaXb = scalaxb.fromXML[Schema](
131 | XML.load(schema))
132 |
133 | val ns = schemaXb.targetNamespace.get.toString
134 |
135 | val visitor = new TreeCreatingVisitor()
136 |
137 | new SchemaTraversor(schemaXb, rootElement, visitor).traverse
138 | println("tree:\n" + visitor)
139 |
140 | new FormCreator(Options(ns, Prefix(idPrefix)),
141 | visitor.configuration,
142 | visitor.rootNode).text
143 | }
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/xsd-forms-html-js/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.github.davidmoten.xsdforms
5 | xsd-forms
6 | 0.2.2-SNAPSHOT
7 |
8 | xsd-forms-html-js
9 | ${project.artifactId}
10 |
11 |
12 | junit
13 | junit
14 | 4.13.2
15 | test
16 |
17 |
18 |
19 |
20 |
21 | maven-resources-plugin
22 | 3.3.1
23 |
24 |
25 | default-resources
26 |
27 | resources
28 |
29 |
30 |
31 | js
32 | css
33 | txt
34 |
35 |
36 |
37 |
38 |
39 |
40 | ${project.parent.groupId}
41 | file-list-maven-plugin
42 | ${project.parent.version}
43 |
44 |
45 | add-file-list
46 | generate-resources
47 |
48 | list
49 |
50 |
51 | ${project.build.directory}/generated-resources/file-list.txt
52 |
53 |
54 |
55 |
56 |
57 | org.codehaus.mojo
58 | build-helper-maven-plugin
59 | 3.3.0
60 |
61 |
62 | add-resources
63 | generate-resources
64 |
65 | add-resource
66 |
67 |
68 |
69 |
70 | ${project.build.directory}/generated-resources
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
84 |
85 | org.eclipse.m2e
86 | lifecycle-mapping
87 | 1.0.0
88 |
89 |
90 |
91 |
92 |
93 | com.github.davidmoten.xsdforms
94 | file-list-maven-plugin
95 | [0.1-SNAPSHOT,)
96 |
97 | list
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | org.apache.maven.plugins
107 | maven-resources-plugin
108 | [2.5,)
109 |
110 | bundle
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/xsd-forms-generator-webapp/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.github.davidmoten.xsdforms
5 | xsd-forms
6 | 0.2.2-SNAPSHOT
7 |
8 | xsd-forms-generator-webapp
9 | ${project.artifactId}
10 | war
11 |
12 |
13 | javax.servlet
14 | servlet-api
15 | 2.5
16 | provided
17 |
18 |
19 | ${project.parent.groupId}
20 | xsd-forms-generator
21 | ${project.parent.version}
22 |
23 |
24 |
25 | UTF-8
26 | 8.1.16.v20140903
27 | 9998
28 |
29 |
30 |
31 |
32 | org.mortbay.jetty
33 | jetty-maven-plugin
34 | ${jetty.plugin.version}
35 |
36 | 10
37 | foo
38 | ${jetty.stop.port}
39 |
40 | /
41 |
42 | src/main/webapp
43 | ${project.build.directory}/${project.artifactId}-${project.version}
44 |
45 |
46 |
47 |
48 |
49 | org.apache.maven.plugins
50 | maven-dependency-plugin
51 | 3.6.0
52 |
53 |
54 | unpack
55 | generate-resources
56 |
57 | unpack
58 |
59 |
60 |
61 |
62 | ${project.parent.groupId}
63 | xsd-forms-html-js
64 | ${project.parent.version}
65 | jar
66 | true
67 | ${project.build.directory}/${project.artifactId}-${project.version}
68 |
69 |
70 | false
71 | true
72 |
73 |
74 |
75 | package
76 | copy
77 |
78 |
79 |
80 | org.eclipse.jetty
81 | jetty-runner
82 | 9.2.10.v20150310
83 | jetty-runner.jar
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | maven-site-plugin
95 | ${m3.site.version}
96 |
97 | true
98 |
99 |
100 |
102 |
103 | org.eclipse.m2e
104 | lifecycle-mapping
105 | 1.0.0
106 |
107 |
108 |
109 |
110 |
111 |
112 | org.apache.maven.plugins
113 |
114 |
115 | maven-dependency-plugin
116 |
117 |
118 | [2.8,)
119 |
120 |
121 | unpack
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | org.apache.maven.plugins
132 |
133 |
134 | maven-antrun-plugin
135 |
136 |
137 | [1.7,)
138 |
139 |
140 | run
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/resources/demo-form-expected.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | illegal characters <>
4 | default
5 |
6 | default
7 | 1
8 | 10.0435
9 | 1
10 | 123
11 | 2013-12-25
12 | 1973-06-12
13 | 22:45:00
14 | 21:55:00
15 | 2013-12-25T04:45:00
16 | 2002-05-30T09:30:00
17 | false
18 | true
19 | option-1
20 | option-1
21 | A
22 | 1.5
23 | 1
24 | A
25 | B
26 |
27 |
28 | a123
29 |
30 | a123
31 | a123
32 | AB
33 | abc
34 | 123
35 | 123
36 |
37 | 123
38 | 123
39 | 1234
40 | 1234
41 | 1234
42 | 5
43 | 5
44 | 10
45 | 10
46 | 6
47 | 5.0001
48 | 9
49 | 9.9999
50 |
51 | 1901-11-30
52 |
53 | 456
54 | 123
55 | 123
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | false
76 | option-1
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | false
89 | option-1
90 |
91 |
92 |
93 |
94 | false
95 | option-1
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | false
107 | option-1
108 |
109 |
110 | -123
111 | -1234
112 | 12
113 | 12345
114 | -12345
115 | 123456
116 | 0
117 |
118 | name1
119 | value1
120 | group1
121 | category1
122 |
123 | false
124 | true
125 | false
126 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/html/html.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree.html
2 |
3 | import scala.Option.option2Iterable
4 |
5 | /**
6 | * Builds html specifically for xsd-forms.
7 | */
8 | object `package` {}
9 |
10 | private object Html {
11 | val Legend = "legend"
12 | val Div = "div"
13 | val Select = "select"
14 | val Option = "option"
15 | val Label = "label"
16 | val Fieldset = "fieldset"
17 | val Textarea = "textarea"
18 | val Input = "input"
19 | val Id = "id"
20 | val Class = "class"
21 | val Value = "value"
22 | val Enabled = "enabled"
23 | val Checked = "checked"
24 | val Name = "name"
25 | }
26 |
27 | private[tree] class Html {
28 | import Html._
29 | private case class HtmlElement(name: String, hasContent: Boolean)
30 | private val stack = new scala.collection.mutable.Stack[HtmlElement]
31 | //mutable!
32 | private val s = new StringBuffer
33 | //mutable!
34 | private val scriptBuffer = new StringBuffer
35 |
36 | def div(id: Option[String] = None,
37 | classes: List[String] = List(), enabledAttr: Option[String] = None,
38 | content: Option[String] = None) =
39 | element(name = Div, id = id, classes = classes, enabledAttr = enabledAttr,
40 | content = content)
41 |
42 | def select(id: Option[String] = None, name: String,
43 | classes: List[String] = List(),
44 | content: Option[String] = None, number: Option[Int] = None) =
45 | element(name = Select, id = id, classes = classes,
46 | nameAttr = Some(name), numberAttr = number,
47 | content = content)
48 |
49 | def option(id: Option[String] = None,
50 | classes: List[String] = List(),
51 | value: String,
52 | content: Option[String] = None) =
53 | element(name = Html.Option, id = id, classes = classes,
54 | content = content, value = Some(value))
55 |
56 | def label(forInputName: String, id: Option[String] = None,
57 | classes: List[String] = List(), content: Option[String] = None) =
58 | element(
59 | name = Label,
60 | id = id,
61 | forAttr = Some(forInputName),
62 | classes = classes,
63 | content = content)
64 |
65 | def fieldset(
66 | legend: Option[String] = None,
67 | classes: List[String] = List(),
68 | id: Option[String]) = {
69 | element(name = Fieldset, classes = classes, id = id)
70 | legend match {
71 | case Some(x) => element(name = Legend, content = Some(x)).closeTag
72 | case None =>
73 | }
74 | }
75 |
76 | def textarea(id: Option[String] = None,
77 | classes: List[String] = List(),
78 | content: Option[String] = None,
79 | value: Option[String] = None,
80 | name: String, number: Option[Int] = None,
81 | closed: Boolean = false) =
82 | element(name = Textarea,
83 | id = id,
84 | classes = classes,
85 | content = content,
86 | value = value,
87 | nameAttr = Some(name),
88 | numberAttr = number)
89 |
90 | def input(id: Option[String] = None,
91 | classes: List[String] = List(),
92 | content: Option[String] = None,
93 | name: String, value: Option[String] = None,
94 | checked: Option[Boolean] = None,
95 | number: Option[Int] = None,
96 | typ: Option[String]) =
97 | element(name = Input, id = id, classes = classes, checked = checked,
98 | content = content, value = value,
99 | nameAttr = Some(name), typ = typ, numberAttr = number)
100 |
101 | private def classNames(classes: List[String]) =
102 | if (classes.length == 0)
103 | None
104 | else
105 | Some(classes.mkString(" "))
106 |
107 | private def element(name: String,
108 | id: Option[String] = None,
109 | classes: List[String] = List(),
110 | content: Option[String] = None,
111 | value: Option[String] = None,
112 | checked: Option[Boolean] = None,
113 | nameAttr: Option[String] = None,
114 | enabledAttr: Option[String] = None,
115 | forAttr: Option[String] = None,
116 | numberAttr: Option[Int] = None,
117 | typ: Option[String] = None): Html = {
118 | val attributes =
119 | id.map((Id, _)) ++
120 | classNames(classes).map((Class -> _)) ++
121 | value.map((Value, _)) ++
122 | nameAttr.map((Name, _)) ++
123 | enabledAttr.map((Enabled, _)) ++
124 | forAttr.map(("for", _)) ++
125 | typ.map(("type", _)) ++
126 | checked.map(x => (Checked, x.toString)) ++
127 | numberAttr.map(x => ("number", x.toString))
128 | elementBase(name, attributes.toMap, content)
129 | this
130 | }
131 |
132 | private def elementBase(name: String, attributes: Map[String, String],
133 | content: Option[String]): Html = {
134 | stack.push(HtmlElement(name, content.isDefined))
135 | indent
136 | val attributesClause =
137 | attributes.map(x => x._1 + "=\"" + x._2 + "\"").mkString(" ")
138 | append("<" + name + " "
139 | + attributesClause + ">" + content.mkString)
140 | this
141 | }
142 |
143 | private def indent {
144 | val indent = " " * stack.size
145 | append("\n")
146 | append(indent)
147 | }
148 |
149 | private def append(str: String) = {
150 | s.append(str)
151 | this
152 | }
153 |
154 | def closeTag: Html = {
155 | if (stack.isEmpty)
156 | throw new RuntimeException("closeTag called on empty html stack! html so far=\n" + s.toString)
157 | val element = stack.head
158 | if (!element.hasContent) {
159 | indent
160 | }
161 | append("" + element.name + ">");
162 | stack.pop
163 | this
164 | }
165 |
166 | def closeTag(n: Int): Html = {
167 | for (i <- 1 to n)
168 | closeTag
169 | this
170 | }
171 |
172 | def appendScript(s: String) {
173 | scriptBuffer append s
174 | }
175 |
176 | def script = scriptBuffer.toString
177 |
178 | override def toString = s.toString
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/presentation/annotation.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.presentation
2 |
3 | import xsd.Annotatedable
4 |
5 | /**
6 | * Configures presentation of web forms generated by xsd-forms.
7 | */
8 | object `package` {}
9 |
10 | private[xsdforms] object Annotation {
11 | //TODO document each of the annotations in scaladoc
12 |
13 | /**
14 | * Annotation 'label' is the label to be used for the element
15 | * input field. Usually located just left of the input field
16 | * associated with the element with this annotation. If omitted
17 | * the default value is the element name with dashes and underscores
18 | * replaced with spaces then camel cased.
19 | */
20 | val Label = XsdFormsAnnotation("label")
21 |
22 | /**
23 | * Annotation 'choice' If choice=inline then choice is inline
24 | * with radio selector otherwise appears after the group of
25 | * radio selectors.
26 | */
27 | val Choice = XsdFormsAnnotation("choice")
28 |
29 | /**
30 | * For a radio selector, choice label will go against the selector.
31 | * Use 'label' against the element itself (which will be made
32 | * visible by the selector).
33 | */
34 | val ChoiceLabel = XsdFormsAnnotation("choiceLabel")
35 |
36 | /**
37 | * If legend is set then is used as label for a fieldset block.
38 | */
39 | val Legend = XsdFormsAnnotation("legend")
40 |
41 | /**
42 | * 'repeatLabel' is the text on the button that when pressed
43 | * creates another instance of the element or complexType at
44 | * that level. The default is '+'.
45 | */
46 | val RepeatLabel = XsdFormsAnnotation("repeatLabel")
47 |
48 | /**
49 | * 'minOccursZeroLabel' is the button label when a sequence of
50 | * elements (a complex type) has minOccurs="0". Clicking the
51 | * minOccursZero button toggles the visiblity of the sequence.
52 | */
53 | val MinOccursZeroLabel = XsdFormsAnnotation("minOccursZeroLabel")
54 |
55 | /**
56 | * 'removeLabel' is the text on the button that when pressed
57 | * removes the current instance of the element or complexType.
58 | * The default is '-'.
59 | */
60 | val RemoveLabel = XsdFormsAnnotation("removeLabel")
61 |
62 | /**
63 | * 'title' is for the text to be used as the title for an element.
64 | */
65 | val Title = XsdFormsAnnotation("title")
66 |
67 | /**
68 | * 'before' is the text to appear before an element.
69 | */
70 | val Before = XsdFormsAnnotation("before")
71 |
72 | /**
73 | * 'after' is the text to appear after an element.
74 | */
75 | val After = XsdFormsAnnotation("after")
76 |
77 | /**
78 | * if text=textarea then html textarea used as input. Otherwise normal
79 | * short text input used.
80 | */
81 | val Text = XsdFormsAnnotation("text")
82 |
83 | /**
84 | * Specific css for width to be applied to the input element.
85 | */
86 | val Width = XsdFormsAnnotation("width")
87 |
88 | /**
89 | * If selector=radio then radio control used for choice instead
90 | * of drop down.
91 | */
92 | val Selector = XsdFormsAnnotation("selector")
93 |
94 | /**
95 | * If addBlank=true and an enumeration is being displayed (in a
96 | * drop-down) then a blank option will be added to the drop-down
97 | * representing no selection.
98 | */
99 | val AddBlank = XsdFormsAnnotation("addBlank")
100 |
101 | /**
102 | * 'css' can be set to a group of css styles which will be applied to
103 | * the element. For example 'width:20em;font-size:80%'.
104 | */
105 | val Css = XsdFormsAnnotation("css")
106 |
107 | /**
108 | * Validation message to be displayed if the input is assessed
109 | * as invalid.
110 | */
111 | val Validation = XsdFormsAnnotation("validation")
112 |
113 | /**
114 | * Help to display as tooltip if user clicks/hovers input. Not a
115 | * great way of displaying help as it hides whatever is underneath
116 | * it even if temporarily.
117 | */
118 | val Help = XsdFormsAnnotation("help")
119 |
120 | /**
121 | * On a named element with an enumeration type, set annotation
122 | * {{{
123 | * makeVisible="value1->n1,value2->n2"
124 | * }}}
125 | * where value1,value2 are enumerated values and n1,n2 integers are the relative
126 | * indexes (1 equates to the following element at the same level) of the element
127 | * that is to be made visible on selection of that value.
128 | * You can also set makeVisible on a specific member of the enumeration using
129 | * {{{
130 | * makeVisible="n""
131 | * }}}where n is an integer only.
132 | *
133 | * The element that is to be made visible should be annotated with visible='false'.
134 | *
135 | * Make sure you set minOccurs=0 on the element that may be invisible.
136 | *
137 | * This annotation also works with boolean types. Use
138 | * {{{
139 | * makeVisible="true->1"
140 | * }}}
141 | * to make the following element become visible when ticked (and invisible when unticked).
142 | */
143 | val MakeVisible = XsdFormsAnnotation("makeVisible")
144 |
145 | /**
146 | * 'nonRepeatingTitle' is the title displayed after 'title' for a complexType
147 | * that has maxOccurs > 1.
148 | */
149 | val NonRepeatingTitle = XsdFormsAnnotation("nonRepeatingTitle")
150 |
151 | /**
152 | * Annotation 'description' appears just below the input box.
153 | */
154 | val Description = XsdFormsAnnotation("description")
155 |
156 | /**
157 | * 'visible' = false will hide the element at first. This is most
158 | * useful in conjunction with 'makeVisible'.
159 | */
160 | val Visible = XsdFormsAnnotation("visible")
161 |
162 | /**
163 | * 'maxRepeats' should be an integer value >0 for an element and is the
164 | * maximum number of repeats generated in html of the element (all
165 | * be them hidden).
166 | */
167 | val MaxRepeats = XsdFormsAnnotation("maxRepeats")
168 |
169 | val Header = XsdFormsAnnotation("header")
170 |
171 | val Footer = XsdFormsAnnotation("footer")
172 | val ExtraCss = XsdFormsAnnotation("extraCss")
173 | val ExtraImports = XsdFormsAnnotation("extraImports")
174 | val ExtraScript = XsdFormsAnnotation("extraScript")
175 | }
176 |
177 | private[xsdforms] case class XsdFormsAnnotation(name: String) {
178 | //TODO move dep to a util package
179 | import com.github.davidmoten.xsdforms.tree.XsdUtil
180 |
181 | def from(a:Annotatedable) = a.annotation match {
182 | case Some(x) =>
183 | x.attributes.get("@{" + XsdUtil.AppInfoSchema + "}" + name) match {
184 | case Some(y) => Some(y.value.toString)
185 | case None => None
186 | }
187 | case None => None
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/xsd-forms-generator/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.github.davidmoten.xsdforms
5 | xsd-forms
6 | 0.2.2-SNAPSHOT
7 |
8 | xsd-forms-generator
9 | ${project.artifactId}
10 |
11 | 2.53.1
12 | /usr/local/bin/chromedriver
13 | 3.3
14 | 2.6
15 |
16 |
17 |
18 | selenium
19 |
20 |
21 | selenium
22 | true
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | default
31 |
32 |
33 | selenium
34 | !true
35 |
36 |
37 |
38 | **/*SeleniumTest.*
39 |
40 |
41 |
42 |
43 |
44 | ${project.parent.groupId}
45 | xsd-scalaxb
46 | ${project.parent.version}
47 |
48 |
49 | ${project.parent.groupId}
50 | xsd-forms-html-js
51 | ${project.parent.version}
52 |
53 |
54 | commons-io
55 | commons-io
56 | 2.13.0
57 |
58 |
59 |
60 |
61 | junit
62 | junit
63 | 4.13.2
64 | test
65 |
66 |
67 | ${project.parent.groupId}
68 | demo-scalaxb
69 | ${project.parent.version}
70 | test
71 |
72 |
73 | org.seleniumhq.selenium
74 | selenium-server
75 | ${selenium.version}
76 | test
77 |
78 |
79 | org.seleniumhq.selenium
80 | selenium-java
81 | ${selenium.version}
82 | pom
83 | test
84 |
85 |
91 |
92 |
93 | src/main/scala
94 | src/test/scala
95 |
96 |
97 | net.alchim31.maven
98 | scala-maven-plugin
99 | ${scala.plugin.version}
100 |
101 |
102 |
103 | compile
104 | testCompile
105 |
106 |
107 |
108 | -deprecation
109 | -dependencyfile
110 | ${project.build.directory}/.scala_dependencies
111 |
112 |
113 |
114 |
115 |
116 |
117 | org.apache.maven.plugins
118 | maven-surefire-plugin
119 | 3.1.2
120 |
121 | false
122 | true
123 |
124 |
125 |
126 | **/*Test.*
127 | **/*Suite.*
128 |
129 |
130 | ${surefire.excludes}
131 |
132 | -Dwebdriver.chrome.driver=${webdriver.chrome.driver}
133 |
134 |
135 |
136 | org.codehaus.mojo
137 | build-helper-maven-plugin
138 | 3.3.0
139 |
140 |
141 | add-resource
142 | generate-resources
143 |
144 | add-resource
145 |
146 |
147 |
148 |
149 | ${project.build.directory}/generated-resources
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 | org.apache.maven.plugins
159 | maven-source-plugin
160 | 3.3.0
161 |
162 |
163 | attach-sources
164 |
165 | jar
166 |
167 |
168 |
169 |
170 |
171 | org.mortbay.jetty
172 | jetty-maven-plugin
173 | 8.1.16.v20140903
174 |
175 | 0
176 |
177 | /
178 |
179 | src/main/webapp,target/generated-webapp
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/resources/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
220 |
221 |
222 |
223 |
237 |
238 |
239 |
--------------------------------------------------------------------------------
/xsd-scalaxb/src/main/xsd/datatypes.dtd:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
70 |
71 |
81 |
82 |
83 |
84 |
85 |
86 |
89 |
90 |
93 |
94 |
95 |
97 |
102 |
103 |
107 |
111 |
120 |
121 |
125 |
129 |
130 |
134 |
138 |
139 |
140 |
144 |
145 |
149 |
150 |
151 |
155 |
156 |
160 |
161 |
162 |
166 |
167 |
171 |
172 |
173 |
177 |
178 |
182 |
183 |
187 |
188 |
189 |
190 |
193 |
194 |
195 |
199 |
200 |
201 |
202 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/css/xsd-forms-style.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0 0px;
3 | font: normal 62.5% "Lucida Grande", Helvetica, Verdana, Arial;
4 | background-color: #F5F5F5 ;/*#EDFAD9;*/
5 | }
6 |
7 | .clear {
8 | clear:left;
9 | }
10 |
11 | .form {
12 | margin-left: 0px;
13 | max-width: 100%;
14 | }
15 |
16 | .sequence {
17 | clear:left;
18 | }
19 |
20 | .sequence-content {
21 | margin-left: 10px;
22 | }
23 |
24 | .item-title {
25 | clear:left;
26 | font-weight:bold;
27 | margin-top:10px;
28 | margin-left:10px;
29 | }
30 |
31 | .item-before {
32 | clear:left;
33 | margin-top:10px;
34 | margin-left:15px;
35 | padding-bottom:7px;
36 | }
37 |
38 | .item-after {
39 | margin-bottom:10px;
40 | margin-left:15px;
41 | }
42 |
43 | .item {
44 | clear: left;
45 | border-top: 1px solid #C9DCA6;
46 | color: black;
47 | }
48 |
49 | .sequence-number {
50 | padding-top: 13px;
51 | padding-left: 5px;
52 | padding-right: 5px;
53 | width: 2em;
54 | color: gray;
55 | font-size: 52%;
56 | }
57 |
58 | .sequence-label {
59 | margin-top: 10px;
60 | min-width: 100px;
61 | padding-right: 10px;
62 | padding-bottom: 10px;
63 | font-weight: bold;
64 | margin-left:10px;
65 | }
66 |
67 | .choice {
68 | clear:left;
69 | margin-left:10px;
70 | }
71 |
72 | .choice-number {
73 | padding-top: 13px;
74 | padding-left: 5px;
75 | padding-right: 5px;
76 | width: 2em;
77 | color: gray;
78 | font-size: 52%;
79 | }
80 |
81 | .choice-label {
82 | margin-top: 10px;
83 | min-width: 100px;
84 | padding-right: 10px;
85 | padding-bottom: 10px;
86 | font-weight: bold;
87 | }
88 |
89 | .choice-content {
90 |
91 | }
92 |
93 | .choice-item {
94 | /* float:left; */
95 | }
96 |
97 | .item-enclosing {
98 | padding-top:7px;
99 | clear:left;
100 | }
101 |
102 | .item-number {
103 | clear:left;
104 | padding-top: 5px;
105 | padding-left: 5px;
106 | padding-right: 5px;
107 | float: left;
108 | width: 2em;
109 | color: gray;
110 | font-size: 72%;
111 | }
112 |
113 | .item-label {
114 | float: left;
115 | min-width: 100px;
116 | padding-right: 10px;
117 | /** padding-bottom: 10px;**/
118 | padding-top: 4px;
119 |
120 | }
121 |
122 | .item-path {
123 | display:none;
124 | }
125 |
126 | .select {
127 | font-size:100%;
128 | height:20px;
129 | margin-top: 7 px;
130 | margin-bottom: 7 px;
131 | }
132 |
133 | .item-input {
134 | float:left;
135 | }
136 |
137 | .item-input-text {
138 | clear: left;
139 | /* border: #999999 solid thin;
140 | margin-top: 7 px;
141 | */
142 | margin-bottom: 5px;
143 | height:20px;
144 | font-size:100%;
145 | }
146 |
147 | .item-input-textarea {
148 | clear: left;
149 | height: 6em;
150 | width: 25em;
151 | margin-top: 7px;
152 | margin-bottom: 7px;
153 | overflow:auto;
154 | font-size:120%;
155 | }
156 |
157 | .item-description {
158 | margin-left:4em;
159 | margin-bottom:10px;
160 | font-size:85%;
161 | }
162 |
163 | .item-error {
164 | margin-left:0px;
165 | margin-bottom:10px;
166 | margin-top:5px;
167 | max-width:250px;
168 | padding:10px;
169 | font-size:85%;
170 | font-weight:bold;
171 | color:white;
172 | background-color:red;
173 | display: none;
174 | }
175 |
176 | .validationErrors {
177 | background-color:red;
178 | color:white;
179 | font-size:100%;
180 | font-weight: bold;
181 | margin-bottom:10px;
182 | margin-top: 10px;
183 | padding: 10px;
184 | max-width:200px;
185 | display: none;
186 | }
187 |
188 | .non-repeating-title {
189 | font-weight: bold;
190 | clear:left;
191 | margin-left:10px;
192 | padding-top:3px;
193 | margin-top:5px;
194 | }
195 |
196 | .repeating-enclosing {
197 | overflow:hidden;
198 | width:100%;
199 | }
200 |
201 | .repeat-button {
202 | /* display: inline-block; */
203 | /* zoom: 1; */ /* zoom and *display = ie7 hack for display:inline-block */
204 | /* display: inline; */
205 | clear:left;
206 | float:left;
207 | vertical-align: baseline;
208 | margin: 5px 20% 10px 0px;
209 | outline: none;
210 | cursor: pointer;
211 | text-align: center;
212 | text-decoration: none;
213 | font: 11px/100% Arial, Helvetica, sans-serif;
214 | padding: .5em 2em .55em 2em;
215 | text-shadow: 0 1px 1px rgba(0,0,0,.3);
216 | -webkit-border-radius: .5em;
217 | -moz-border-radius: .5em;
218 | border-radius: .5em;
219 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
220 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
221 | box-shadow: 0 1px 2px rgba(0,0,0,.2);
222 | }
223 | .repeat-button:hover {
224 | text-decoration: none;
225 | }
226 | .repeat-button:active {
227 | position: relative;
228 | top: 1px;
229 | }
230 |
231 | .remove-button-container {
232 | overflow:hidden;
233 | width:100%;
234 | }
235 |
236 | .remove-button {
237 | clear:left;
238 | float:left;
239 | vertical-align: baseline;
240 | margin: 5px 20% 10px 50px;
241 | outline: none;
242 | cursor: pointer;
243 | text-align: center;
244 | text-decoration: none;
245 | font: 11px/100% Arial, Helvetica, sans-serif;
246 | padding: .5em 2em .55em 2em;
247 | text-shadow: 0 1px 1px rgba(0,0,0,.3);
248 | -webkit-border-radius: .5em;
249 | -moz-border-radius: .5em;
250 | border-radius: .5em;
251 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
252 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
253 | box-shadow: 0 1px 2px rgba(0,0,0,.2);
254 | }
255 | .remove-button:hover {
256 | text-decoration: none;
257 | }
258 | .remove-button:active {
259 | position: relative;
260 | top: 1px;
261 | }
262 |
263 | .item-add {
264 | display: inline-block;
265 | zoom: 1; /* zoom and *display = ie7 hack for display:inline-block */
266 | display: inline;
267 | vertical-align: baseline;
268 | margin: 0 2px;
269 | outline: none;
270 | cursor: pointer;
271 | text-align: center;
272 | text-decoration: none;
273 | font: 11px/100% Arial, Helvetica, sans-serif;
274 | padding: .5em 2em .55em;
275 | text-shadow: 0 1px 1px rgba(0,0,0,.3);
276 | -webkit-border-radius: .5em;
277 | -moz-border-radius: .5em;
278 | border-radius: .5em;
279 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
280 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
281 | box-shadow: 0 1px 2px rgba(0,0,0,.2);
282 | }
283 | .item-add:hover {
284 | text-decoration: none;
285 | }
286 | .item-add:active {
287 | position: relative;
288 | top: 1px;
289 | }
290 |
291 | .group-add {
292 | /* display: inline-block; */
293 | /* zoom: 1; */ /* zoom and *display = ie7 hack for display:inline-block */
294 | /* display: inline; */
295 | vertical-align: baseline;
296 | margin: 0px 20% 10px 20%;
297 | outline: none;
298 | cursor: pointer;
299 | text-align: center;
300 | text-decoration: none;
301 | font: 11px/100% Arial, Helvetica, sans-serif;
302 | padding: .5em 2em .55em 2em;
303 | text-shadow: 0 1px 1px rgba(0,0,0,.3);
304 | -webkit-border-radius: .5em;
305 | -moz-border-radius: .5em;
306 | border-radius: .5em;
307 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
308 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
309 | box-shadow: 0 1px 2px rgba(0,0,0,.2);
310 | }
311 | .group-add:hover {
312 | text-decoration: none;
313 | }
314 | .group-add:active {
315 | position: relative;
316 | top: 1px;
317 | }
318 |
319 | #submit {
320 | border: #999999 solid thin;
321 | width: 6em;
322 | text-align: center;
323 | margin-left: 20px;
324 | margin-top:20px;
325 | padding:5px;
326 | background:white;
327 | }
328 |
329 | .invisible {
330 | display:none;
331 | }
332 |
333 | .bigrounded {
334 | -webkit-border-radius: 2em;
335 | -moz-border-radius: 2em;
336 | border-radius: 2em;
337 | }
338 | .medium {
339 | font-size: 12px;
340 | padding: .4em 1.5em .42em;
341 | }
342 | .small {
343 | font-size: 11px;
344 | padding: .2em 1em .275em;
345 | }
346 |
347 | /* white */
348 | .white {
349 | color: #606060;
350 | border: solid 1px #b7b7b7;
351 | background: #fff;
352 | background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#ededed));
353 | background: -moz-linear-gradient(top, #fff, #ededed);
354 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#ededed');
355 | }
356 | .white:hover {
357 | background: #ededed;
358 | background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#dcdcdc));
359 | background: -moz-linear-gradient(top, #fff, #dcdcdc);
360 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dcdcdc');
361 | }
362 | .white:active {
363 | color: #999;
364 | background: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#fff));
365 | background: -moz-linear-gradient(top, #ededed, #fff);
366 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#ffffff');
367 | }
368 |
369 |
370 | em {
371 | color: red;
372 | }
373 |
374 | .failure {
375 | color:red;
376 | font-size: 150%;
377 | }
378 |
379 |
380 | .min-occurs-zero {
381 | float:left;
382 | }
383 |
384 | .min-occurs-zero-container {
385 | overflow:hidden;
386 | width: 100%;
387 | margin-top: 0.5em;
388 | margin-left: 1em;
389 | }
390 |
391 | .min-occurs-zero-label {
392 | float:left;
393 | margin-right:1em;
394 | }
395 |
396 | .clr {
397 | clear:left;
398 | }
399 |
--------------------------------------------------------------------------------
/xsd-forms-html-js/src/main/resources/css/xsd-forms-style.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0 0px;
3 | font: normal 62.5% "Lucida Grande", Helvetica, Verdana, Arial;
4 | background-color: #F5F5F5 ;/*#EDFAD9;*/
5 | }
6 |
7 | .clear {
8 | clear:left;
9 | }
10 |
11 | .form {
12 | margin-left: 0px;
13 | max-width: 100%;
14 | }
15 |
16 | .sequence {
17 | clear:left;
18 | }
19 |
20 | .sequence-content {
21 | margin-left: 10px;
22 | }
23 |
24 | .item-title {
25 | clear:left;
26 | font-weight:bold;
27 | margin-top:10px;
28 | margin-left:10px;
29 | }
30 |
31 | .item-before {
32 | clear:left;
33 | margin-top:10px;
34 | margin-left:15px;
35 | padding-bottom:7px;
36 | }
37 |
38 | .item-after {
39 | margin-bottom:10px;
40 | margin-left:15px;
41 | }
42 |
43 | .item {
44 | clear: left;
45 | border-top: 1px solid #C9DCA6;
46 | color: black;
47 | }
48 |
49 | .sequence-number {
50 | padding-top: 13px;
51 | padding-left: 5px;
52 | padding-right: 5px;
53 | width: 2em;
54 | color: gray;
55 | font-size: 52%;
56 | }
57 |
58 | .sequence-label {
59 | margin-top: 10px;
60 | min-width: 100px;
61 | padding-right: 10px;
62 | padding-bottom: 10px;
63 | font-weight: bold;
64 | margin-left:10px;
65 | }
66 |
67 | .choice {
68 | clear:left;
69 | margin-left:10px;
70 | }
71 |
72 | .choice-number {
73 | padding-top: 13px;
74 | padding-left: 5px;
75 | padding-right: 5px;
76 | width: 2em;
77 | color: gray;
78 | font-size: 52%;
79 | }
80 |
81 | .choice-label {
82 | margin-top: 10px;
83 | min-width: 100px;
84 | padding-right: 10px;
85 | padding-bottom: 10px;
86 | font-weight: bold;
87 | }
88 |
89 | .choice-content {
90 |
91 | }
92 |
93 | .choice-item {
94 | /* float:left; */
95 | }
96 |
97 | .item-enclosing {
98 | padding-top:7px;
99 | clear:left;
100 | }
101 |
102 | .item-number {
103 | clear:left;
104 | padding-top: 5px;
105 | padding-left: 5px;
106 | padding-right: 5px;
107 | float: left;
108 | width: 2em;
109 | color: gray;
110 | font-size: 72%;
111 | }
112 |
113 | .item-label {
114 | float: left;
115 | min-width: 100px;
116 | padding-right: 10px;
117 | /** padding-bottom: 10px;**/
118 | padding-top: 4px;
119 |
120 | }
121 |
122 | .item-path {
123 | display:none;
124 | }
125 |
126 | .select {
127 | font-size:100%;
128 | height:20px;
129 | margin-top: 7 px;
130 | margin-bottom: 7 px;
131 | }
132 |
133 | .item-input {
134 | float:left;
135 | }
136 |
137 | .item-input-text {
138 | clear: left;
139 | /* border: #999999 solid thin;
140 | margin-top: 7 px;
141 | */
142 | margin-bottom: 5px;
143 | height:20px;
144 | font-size:100%;
145 | }
146 |
147 | .item-input-textarea {
148 | clear: left;
149 | height: 6em;
150 | width: 25em;
151 | margin-top: 7px;
152 | margin-bottom: 7px;
153 | overflow:auto;
154 | font-size:120%;
155 | }
156 |
157 | .item-description {
158 | margin-left:4em;
159 | margin-bottom:10px;
160 | font-size:85%;
161 | }
162 |
163 | .item-error {
164 | margin-left:0px;
165 | margin-bottom:10px;
166 | margin-top:5px;
167 | max-width:250px;
168 | padding:10px;
169 | font-size:85%;
170 | font-weight:bold;
171 | color:white;
172 | background-color:red;
173 | display: none;
174 | }
175 |
176 | .validationErrors {
177 | background-color:red;
178 | color:white;
179 | font-size:100%;
180 | font-weight: bold;
181 | margin-bottom:10px;
182 | margin-top: 10px;
183 | padding: 10px;
184 | max-width:200px;
185 | display: none;
186 | }
187 |
188 | .non-repeating-title {
189 | font-weight: bold;
190 | clear:left;
191 | margin-left:10px;
192 | padding-top:3px;
193 | margin-top:5px;
194 | }
195 |
196 | .repeating-enclosing {
197 | overflow:hidden;
198 | width:100%;
199 | }
200 |
201 | .repeat-button {
202 | /* display: inline-block; */
203 | /* zoom: 1; */ /* zoom and *display = ie7 hack for display:inline-block */
204 | /* display: inline; */
205 | clear:left;
206 | float:left;
207 | vertical-align: baseline;
208 | margin: 5px 20% 10px 0px;
209 | outline: none;
210 | cursor: pointer;
211 | text-align: center;
212 | text-decoration: none;
213 | font: 11px/100% Arial, Helvetica, sans-serif;
214 | padding: .5em 2em .55em 2em;
215 | text-shadow: 0 1px 1px rgba(0,0,0,.3);
216 | -webkit-border-radius: .5em;
217 | -moz-border-radius: .5em;
218 | border-radius: .5em;
219 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
220 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
221 | box-shadow: 0 1px 2px rgba(0,0,0,.2);
222 | }
223 | .repeat-button:hover {
224 | text-decoration: none;
225 | }
226 | .repeat-button:active {
227 | position: relative;
228 | top: 1px;
229 | }
230 |
231 | .remove-button-container {
232 | overflow:hidden;
233 | width:100%;
234 | }
235 |
236 | .remove-button {
237 | clear:left;
238 | float:left;
239 | vertical-align: baseline;
240 | margin: 5px 20% 10px 50px;
241 | outline: none;
242 | cursor: pointer;
243 | text-align: center;
244 | text-decoration: none;
245 | font: 11px/100% Arial, Helvetica, sans-serif;
246 | padding: .5em 2em .55em 2em;
247 | text-shadow: 0 1px 1px rgba(0,0,0,.3);
248 | -webkit-border-radius: .5em;
249 | -moz-border-radius: .5em;
250 | border-radius: .5em;
251 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
252 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
253 | box-shadow: 0 1px 2px rgba(0,0,0,.2);
254 | }
255 | .remove-button:hover {
256 | text-decoration: none;
257 | }
258 | .remove-button:active {
259 | position: relative;
260 | top: 1px;
261 | }
262 |
263 | .item-add {
264 | display: inline-block;
265 | zoom: 1; /* zoom and *display = ie7 hack for display:inline-block */
266 | display: inline;
267 | vertical-align: baseline;
268 | margin: 0 2px;
269 | outline: none;
270 | cursor: pointer;
271 | text-align: center;
272 | text-decoration: none;
273 | font: 11px/100% Arial, Helvetica, sans-serif;
274 | padding: .5em 2em .55em;
275 | text-shadow: 0 1px 1px rgba(0,0,0,.3);
276 | -webkit-border-radius: .5em;
277 | -moz-border-radius: .5em;
278 | border-radius: .5em;
279 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
280 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
281 | box-shadow: 0 1px 2px rgba(0,0,0,.2);
282 | }
283 | .item-add:hover {
284 | text-decoration: none;
285 | }
286 | .item-add:active {
287 | position: relative;
288 | top: 1px;
289 | }
290 |
291 | .group-add {
292 | /* display: inline-block; */
293 | /* zoom: 1; */ /* zoom and *display = ie7 hack for display:inline-block */
294 | /* display: inline; */
295 | vertical-align: baseline;
296 | margin: 0px 20% 10px 20%;
297 | outline: none;
298 | cursor: pointer;
299 | text-align: center;
300 | text-decoration: none;
301 | font: 11px/100% Arial, Helvetica, sans-serif;
302 | padding: .5em 2em .55em 2em;
303 | text-shadow: 0 1px 1px rgba(0,0,0,.3);
304 | -webkit-border-radius: .5em;
305 | -moz-border-radius: .5em;
306 | border-radius: .5em;
307 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
308 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
309 | box-shadow: 0 1px 2px rgba(0,0,0,.2);
310 | }
311 | .group-add:hover {
312 | text-decoration: none;
313 | }
314 | .group-add:active {
315 | position: relative;
316 | top: 1px;
317 | }
318 |
319 | #submit {
320 | border: #999999 solid thin;
321 | width: 6em;
322 | text-align: center;
323 | margin-left: 20px;
324 | margin-top:20px;
325 | padding:5px;
326 | background:white;
327 | }
328 |
329 | .invisible {
330 | display:none;
331 | }
332 |
333 | .bigrounded {
334 | -webkit-border-radius: 2em;
335 | -moz-border-radius: 2em;
336 | border-radius: 2em;
337 | }
338 | .medium {
339 | font-size: 12px;
340 | padding: .4em 1.5em .42em;
341 | }
342 | .small {
343 | font-size: 11px;
344 | padding: .2em 1em .275em;
345 | }
346 |
347 | /* white */
348 | .white {
349 | color: #606060;
350 | border: solid 1px #b7b7b7;
351 | background: #fff;
352 | background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#ededed));
353 | background: -moz-linear-gradient(top, #fff, #ededed);
354 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#ededed');
355 | }
356 | .white:hover {
357 | background: #ededed;
358 | background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#dcdcdc));
359 | background: -moz-linear-gradient(top, #fff, #dcdcdc);
360 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dcdcdc');
361 | }
362 | .white:active {
363 | color: #999;
364 | background: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#fff));
365 | background: -moz-linear-gradient(top, #ededed, #fff);
366 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#ffffff');
367 | }
368 |
369 |
370 | em {
371 | color: red;
372 | }
373 |
374 | .failure {
375 | color:red;
376 | font-size: 150%;
377 | }
378 |
379 |
380 | .min-occurs-zero {
381 | float:left;
382 | }
383 |
384 | .min-occurs-zero-container {
385 | overflow:hidden;
386 | width: 100%;
387 | margin-top: 0.5em;
388 | margin-left: 1em;
389 | }
390 |
391 | .min-occurs-zero-label {
392 | float:left;
393 | margin-right:1em;
394 | }
395 |
396 | .clr {
397 | clear:left;
398 | }
399 |
--------------------------------------------------------------------------------
/xsd-scalaxb/src/main/xsd/xml.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
lang (as an attribute name)
49 |
50 | denotes an attribute whose value
51 | is a language code for the natural language of the content of
52 | any element; its value is inherited. This name is reserved
53 | by virtue of its definition in the XML specification.
54 |
55 |
56 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
space (as an attribute name)
95 |
96 | denotes an attribute whose
97 | value is a keyword indicating what whitespace processing
98 | discipline is intended for the content of the element; its
99 | value is inherited. This name is reserved by virtue of its
100 | definition in the XML specification.
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
base (as an attribute name)
118 |
119 | denotes an attribute whose value
120 | provides a URI to be used as the base for interpreting any
121 | relative URIs in the scope of the element on which it
122 | appears; its value is inherited. This name is reserved
123 | by virtue of its definition in the XML Base specification.
124 |
125 |
126 | See http://www.w3.org/TR/xmlbase/
128 | for information about this attribute.
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
id (as an attribute name)
141 |
142 | denotes an attribute whose value
143 | should be interpreted as if declared to be of type ID.
144 | This name is reserved by virtue of its definition in the
145 | xml:id specification.
146 |
147 |
148 | See http://www.w3.org/TR/xml-id/
150 | for information about this attribute.
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
Father (in any context at all)
169 |
170 |
171 |
172 | denotes Jon Bosak, the chair of
173 | the original XML Working Group. This name is reserved by
174 | the following decision of the W3C XML Plenary and
175 | XML Coordination groups:
176 |
177 |
178 |
179 | In appreciation for his vision, leadership and
180 | dedication the W3C XML Plenary on this 10th day of
181 | February, 2000, reserves for Jon Bosak in perpetuity
182 | the XML name "xml:Father".
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 | This schema defines attributes and an attribute group suitable
198 | for use by schemas wishing to allow xml:base,
199 | xml:lang, xml:space or
200 | xml:id attributes on elements they define.
201 |
202 |
203 | To enable this, such a schema must import this schema for
204 | the XML namespace, e.g. as follows:
205 |
206 |
207 | <schema . . .>
208 | . . .
209 | <import namespace="http://www.w3.org/XML/1998/namespace"
210 | schemaLocation="http://www.w3.org/2001/xml.xsd"/>
211 |
212 |
213 | or
214 |
215 |
216 | <import namespace="http://www.w3.org/XML/1998/namespace"
217 | schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
218 |
219 |
220 | Subsequently, qualified reference to any of the attributes or the
221 | group defined below will have the desired effect, e.g.
222 |
223 |
224 | <type . . .>
225 | . . .
226 | <attributeGroup ref="xml:specialAttrs"/>
227 |
228 |
229 | will define a type which will schema-validate an instance element
230 | with any of those attributes.
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 | In keeping with the XML Schema WG's standard versioning
244 | policy, this schema document will persist at
245 |
246 | http://www.w3.org/2009/01/xml.xsd .
247 |
248 |
249 | At the date of issue it can also be found at
250 |
251 | http://www.w3.org/2001/xml.xsd .
252 |
253 |
254 | The schema document at that URI may however change in the future,
255 | in order to remain compatible with the latest version of XML
256 | Schema itself, or with the XML namespace itself. In other words,
257 | if the XML Schema or XML namespaces change, the version of this
258 | document at
259 | http://www.w3.org/2001/xml.xsd
260 |
261 | will change accordingly; the version at
262 |
263 | http://www.w3.org/2009/01/xml.xsd
264 |
265 | will not change.
266 |
267 |
268 | Previous dated (and unchanging) versions of this schema
269 | document are at:
270 |
271 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/element-wrapper.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | /**
4 | * **************************************************************
5 | *
6 | * ElementWrapper
7 | *
8 | *
9 | * **************************************************************
10 | */
11 |
12 | import xsd.Element
13 |
14 | private[tree] case class ElementWrapper(element: Element,
15 | uniqueId: String = java.util.UUID.randomUUID.toString) {
16 |
17 | import com.github.davidmoten.xsdforms.presentation._
18 | import com.github.davidmoten.xsdforms.presentation.Css._
19 | import ElementWrapper._
20 |
21 | private val e = element
22 |
23 | def hasButton =
24 | e.maxOccurs != "1" && e.minOccurs.toString != e.maxOccurs
25 |
26 | def get(key: XsdFormsAnnotation) =
27 | key.from(this)
28 |
29 | def visibility =
30 | get(Annotation.Visible) match {
31 | case Some("false") => Some(ClassInvisible)
32 | case _ => None
33 | }
34 |
35 | def isMinOccursZero =
36 | e.minOccurs.intValue == 0 && get(Annotation.Visible) != Some("false")
37 |
38 | def isTextArea =
39 | get(Annotation.Text) match {
40 | case Some(t) if (t == "textarea") => true
41 | case _ => false
42 | }
43 |
44 | def isRadio =
45 | //TODO add check is enumeration as well
46 | get(Annotation.Selector) match {
47 | case Some("radio") => true
48 | case _ => false
49 | }
50 |
51 | def isMultiple: Boolean =
52 | return (e.maxOccurs == "unbounded" || e.maxOccurs.toInt > 1)
53 |
54 | def repeats: Range = 1 to numInstances
55 |
56 | private def numInstances: Int = {
57 |
58 | val n = if (e.maxOccurs == "unbounded")
59 | NumInstancesForMultiple
60 | else
61 | e.maxOccurs.toInt
62 |
63 | get(Annotation.MaxRepeats) match {
64 | case Some(m) => Math.min(n, m.toInt)
65 | case _ => n
66 | }
67 | }
68 |
69 | private def getLabelFromName =
70 | e.name.get
71 | .replaceAll("-", " ")
72 | .replaceAll("_", " ")
73 | .split(" ")
74 | .map(s =>
75 | Character.toUpperCase(s.charAt(0))
76 | + s.substring(1, s.length))
77 | .mkString(" ")
78 |
79 | def getLabelFromNameOrAnnotation: String = {
80 | val name = getLabelFromName
81 | get(Annotation.Label) match {
82 | case Some(x: String) => x
83 | case _ => name
84 | }
85 | }
86 |
87 | }
88 |
89 | private[tree] case class QN(namespace: String, localPart: String)
90 |
91 | private[tree] sealed trait InputType {
92 | val name: String;
93 | }
94 | private[tree] case object Checkbox extends InputType {
95 | val name = "checkbox";
96 | }
97 | private[tree] case object TextBox extends InputType {
98 | val name = "text"
99 | }
100 |
101 | import xsd.Restriction
102 | import xsd.SimpleRestrictionModelSequence
103 | import javax.xml.namespace.QName
104 |
105 | private[tree] class MyRestriction(qName: QName)
106 | extends Restriction(None, SimpleRestrictionModelSequence(),
107 | None, Some(qName), Map())
108 |
109 | /**
110 | * **************************************************************
111 | *
112 | * ElementWrapper object
113 | *
114 | *
115 | * **************************************************************
116 | */
117 |
118 | private[tree] object ElementWrapper {
119 |
120 | import com.github.davidmoten.xsdforms.presentation._
121 | import Css._
122 | import xsd.Annotatedable
123 | import xsd.Restriction
124 | import xsd.NoFixedFacet
125 | import xsd.SimpleType
126 | import xsd.Pattern
127 | import xsd.ParticleOption
128 | import Util._
129 | import XsdUtil._
130 | import javax.xml.namespace.QName
131 | import scalaxb.DataRecord
132 |
133 | implicit def unwrap(wrapped: ElementWrapper): Element = wrapped.element
134 |
135 | val NumInstancesForMultiple = 5
136 |
137 | def valById(id: String) = "encodedValueById(\"" + id + "\")"
138 |
139 | def defaultValue(value: Option[String], r: Restriction): Option[String] = {
140 | value match {
141 | case Some(v) => {
142 | toQN(r) match {
143 | // drop the seconds off the time so js timepicker is happy
144 | case QN(xs, XsdTime.name) => Some(v.substring(0, 5))
145 | case QN(xs, XsdDateTime.name) => Some(v.substring(0, 16))
146 | case _ => value
147 | }
148 | }
149 | case None => value
150 | }
151 | }
152 |
153 | def isEnumeration(r: Restriction) =
154 | !getEnumeration(r).isEmpty
155 |
156 | def getEnumeration(r: Restriction): Seq[(String, NoFixedFacet)] =
157 | r.simpleRestrictionModelSequence3.facetsOption2.seq.map(
158 | _.value match {
159 | case y: NoFixedFacet => {
160 | val label = Annotation.Label.from(y) match {
161 | case Some(x) => x
162 | case None => y.valueAttribute
163 | }
164 | Some((label, y))
165 | }
166 | case _ => None
167 | }).flatten
168 |
169 | def toQN(r: Restriction): QN = toQN(r.base.get)
170 |
171 | private def toQN(qName: QName): QN =
172 | QN(qName.getNamespaceURI(), qName.getLocalPart())
173 |
174 | def getBasePattern(qn: QN) = {
175 |
176 | qn match {
177 | case QN(xs, XsdDecimal.name) => XsdDecimal.pattern
178 | case QN(xs, XsdInteger.name) => XsdInteger.pattern
179 | case QN(xs, XsdInt.name) => XsdInt.pattern
180 | case QN(xs, XsdLong.name) => XsdLong.pattern
181 | case QN(xs, XsdShort.name) => XsdShort.pattern
182 | case QN(xs, XsdPositiveInteger.name) => XsdPositiveInteger.pattern
183 | case QN(xs, XsdNonPositiveInteger.name) => XsdNonPositiveInteger.pattern
184 | case QN(xs, XsdNegativeInteger.name) => XsdNegativeInteger.pattern
185 | case QN(xs, XsdNonNegativeInteger.name) => XsdNonNegativeInteger.pattern
186 | case QN(xs, XsdDouble.name) => XsdDouble.pattern
187 | case QN(xs, XsdFloat.name) => XsdFloat.pattern
188 | case _ => None
189 | }
190 | }
191 |
192 | def getLabel(node: Node, typ: Option[SimpleType]) =
193 | {
194 | val e = node.element
195 | val label = e.getLabelFromNameOrAnnotation
196 |
197 | val mustOccur = e.minOccurs.intValue > 0
198 | val isText = e.typeValue match {
199 | case Some(x: QName) => x == qn("string")
200 | case _ => false
201 | }
202 | val mandatory = typ match {
203 | case None => mustOccur && !isText
204 | case Some(x) => (
205 | x.simpleDerivationOption3.value match {
206 | case y: Restriction =>
207 | (getInputType(y) match {
208 | case Checkbox => true
209 | case TextBox => isMandatory(node, y)
210 | })
211 | case _ =>
212 | !isText
213 | })
214 | }
215 | if (mandatory) label + "* "
216 | else label
217 | }
218 |
219 | def isMandatory(node: Node, r: Restriction): Boolean = {
220 | val e = node.element
221 | val patterns =
222 | node match {
223 | case b: NodeBasic => getPatterns(b)
224 | case _ => getPatterns(r)
225 | }
226 | getInputType(r) == TextBox &&
227 | e.minOccurs.intValue == 1 &&
228 | ((patterns.size > 0 &&
229 | !patterns.exists(java.util.regex.Pattern.matches(_, ""))) || isEnum(r))
230 | }
231 |
232 | def isEnum(r: Restriction) =
233 | r.simpleRestrictionModelSequence3
234 | .facetsOption2
235 | .filter(x => toQName(x) == qn("enumeration"))
236 | .size > 0
237 |
238 | def restriction(node: NodeBasic): Restriction =
239 | node match {
240 | case n: NodeSimpleType => restriction(n)
241 | case n: NodeBaseType => restriction(n)
242 | }
243 |
244 | def restriction(node: NodeSimpleType): Restriction =
245 | node.typ.simpleDerivationOption3.value match {
246 | case x: Restriction => x
247 | case _ => Util.unexpected
248 | }
249 |
250 | private def restriction(node: NodeBaseType) =
251 | new MyRestriction(node.typ.qName)
252 |
253 | def getPatterns(node: NodeBasic): Seq[String] =
254 | {
255 | val r = restriction(node)
256 |
257 | val explicitPatterns = getPatterns(r)
258 |
259 | val qn = toQN(r)
260 |
261 | //calculate implicit patterns for dates, times, and datetimes
262 | val implicitPatterns =
263 | qn match {
264 | case QN(xs, XsdDate.name) =>
265 | Some("\\d\\d\\d\\d-\\d\\d-\\d\\d")
266 | //TODO why spaces on end of time?
267 | case QN(xs, XsdTime.name) =>
268 | Some("\\d\\d:\\d\\d *")
269 | case QN(xs, XsdDateTime.name) =>
270 | Some("\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d")
271 | case _ => None
272 | }
273 |
274 | explicitPatterns ++ implicitPatterns
275 | }
276 |
277 | private def getPatterns(r: Restriction): Seq[String] =
278 | r.simpleRestrictionModelSequence3.facetsOption2.seq.flatMap(f => {
279 | f match {
280 | case DataRecord(xs, Some("pattern"), x: Pattern) =>
281 | Some(x.valueAttribute)
282 | case _ => None
283 | }
284 | })
285 |
286 | def getInputType(r: Restriction): InputType = {
287 | val qn = toQN(r)
288 | qn match {
289 | case QN(xs, XsdBoolean.name) => Checkbox
290 | case _ => TextBox
291 | }
292 | }
293 |
294 | def isCheckbox(node: NodeBasic) =
295 | Checkbox == getInputType(restriction(node))
296 |
297 | def displayChoiceInline(choice: Choice) =
298 | "inline" == Annotation.Choice.from(choice.group).mkString
299 |
300 | def getChoiceLabel(p: ParticleOption): String = {
301 |
302 | val labels =
303 | p match {
304 | case x: Element => {
305 | Annotation.ChoiceLabel.from(x) ++
306 | Annotation.Label.from(x) ++
307 | Some(ElementWrapper(x).getLabelFromNameOrAnnotation)
308 | }
309 | case _ => unexpected
310 | }
311 | labels.head
312 | }
313 |
314 | def isMultiple(node: Node): Boolean =
315 | node.element.isMultiple
316 |
317 | def repeats(node: Node): Range = node.element.repeats
318 |
319 | def getExtraClasses(qn: QN) = qn match {
320 | case QN(xs, XsdDate.name) => ClassDatePicker + " "
321 | case QN(xs, XsdDateTime.name) => ClassDateTimePicker + " "
322 | case QN(xs, XsdTime.name) => ClassTimePicker + " "
323 | case _ => ""
324 | }
325 |
326 | }
327 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/main/scala/com/github/davidmoten/xsdforms/tree/traversor.scala:
--------------------------------------------------------------------------------
1 | package com.github.davidmoten.xsdforms.tree
2 |
3 | import xsd._
4 | import javax.xml.namespace.QName
5 | import scalaxb._
6 |
7 | /**
8 | * **************************************************************
9 | *
10 | * SchemaTraversor
11 | *
12 | *
13 | * **************************************************************
14 | */
15 |
16 | private case class DataRecordWithQName[T](d: DataRecord[T]) {
17 | import XsdUtil._
18 | def qName = toQName(d)
19 | }
20 |
21 |
22 | private[xsdforms] class SchemaTraversor(s: Schema, rootElement: Option[String], visitor: Visitor) {
23 | import Util._
24 | import XsdUtil._
25 | import com.github.davidmoten.xsdforms.presentation._
26 | import com.github.davidmoten.xsdforms.Configuration
27 | private implicit def toDataRecordWithQName[T](d:DataRecord[T]) = DataRecordWithQName(d)
28 |
29 | val extensionStack = new scala.collection.mutable.Stack[ExtensionTypable]
30 | val extensionsIncludedInBaseSequence = new scala.collection.mutable.Stack[Boolean]
31 |
32 | private val topLevelElements =
33 | s.schemasequence1.flatMap(_.schemaTopOption1.value match {
34 | case y: TopLevelElement => Some(y)
35 | case _ => None
36 | })
37 |
38 | private val topLevelComplexTypes = s
39 | .schemasequence1
40 | .flatMap(_.schemaTopOption1.value match {
41 | case y: TopLevelComplexType => Some(y)
42 | case _ => None
43 | })
44 |
45 | private val topLevelSimpleTypes = s
46 | .schemasequence1.flatMap(_.schemaTopOption1.value match {
47 | case y: TopLevelSimpleType => Some(y)
48 | case _ => None
49 | })
50 |
51 | private val targetNs = s.targetNamespace.getOrElse(
52 | unexpected("schema must have targetNamespace attribute")).toString
53 |
54 | private val schemaTypes =
55 | (topLevelComplexTypes.map(x => (qn(targetNs, x.name.get), x))
56 | ++ (topLevelSimpleTypes.map(x => (qn(targetNs, x.name.get), x)))).toMap;
57 |
58 | private val baseTypes =
59 | Set(XsdDecimal, XsdString, XsdInteger, XsdDate, XsdDateTime, XsdTime,
60 | XsdBoolean, XsdInt, XsdLong, XsdShort, XsdPositiveInteger,
61 | XsdNegativeInteger, XsdNonPositiveInteger, XsdNonNegativeInteger,
62 | XsdDouble, XsdFloat)
63 | .map(qn(_))
64 |
65 | private def getType(q: QName): AnyRef = {
66 | schemaTypes.get(q) match {
67 | case Some(x: Annotatedable) => return x
68 | case _ =>
69 | if (baseTypes contains q) return BaseType(q)
70 | else unexpected("unrecognized type: " + q)
71 | }
72 | }
73 |
74 | private case class MyType(typeValue: AnyRef)
75 |
76 | /**
77 | * Visits the element definition tree.
78 | */
79 | def traverse {
80 | topLevelAnnotations
81 | val element =
82 | if (rootElement.isDefined)
83 | topLevelElements.find(
84 | _.name match {
85 | case Some(y) => y equals rootElement.get
86 | case None => false
87 | }).getOrElse(unexpected("did not find element " + rootElement.get))
88 | else if (topLevelElements.length == 0)
89 | unexpected("no top level elements specified in schema!")
90 | else
91 | topLevelElements(0)
92 |
93 | process(element)
94 | }
95 |
96 | private def topLevelAnnotations {
97 | //first get the children of the annotation - appinfo element
98 | val children = s.schemaoption
99 | .filter(_.qName == qn(XsdAnnotation))
100 | .map(_.value)
101 | .map(x => x match {
102 | case y: Annotation => y
103 | case _ => unexpected
104 | })
105 | .map(_.annotationoption)
106 | .flatten
107 | .filter(toQName(_) == QnXsdAppInfo)
108 | .map(_.value)
109 | .map(x => x match {
110 | case y: Appinfo => y
111 | case _ => unexpected
112 | })
113 | .map(_.mixed)
114 | .flatten
115 |
116 | def extract(elementName: String):Option[String] =
117 | children
118 | .filter(_.key.isDefined)
119 | .filter(_.qName == qn(AppInfoSchema, elementName))
120 | .map(_.value)
121 | .map(x => scala.xml.XML.loadString(x.toString))
122 | .map(_.text).headOption
123 |
124 | val header = extract(Annotation.Header.name)
125 | val footer = extract(Annotation.Footer.name)
126 | val extraImports = extract(Annotation.ExtraImports.name)
127 | val extraScript = extract(Annotation.ExtraScript.name)
128 | val extraCss = extract(Annotation.ExtraCss.name)
129 | val configuration = Configuration(header, footer, extraImports, extraScript, extraCss)
130 | visitor.configuration(configuration)
131 | }
132 |
133 | private def process(e: Element) {
134 | e.typeValue match {
135 | case Some(x: QName) => process(e, MyType(getType(x)))
136 | case None => {
137 | e.elementoption match {
138 | case Some(x: DataRecord[ElementOption]) => {
139 | x.value match {
140 | case y: LocalComplexType => process(e, y)
141 | case y: LocalSimpleType => process(e, y)
142 | case _ => unexpected
143 | }
144 | }
145 | case _ => unexpected("unsupported " + e)
146 | }
147 | }
148 | case _ => unexpected
149 | }
150 | }
151 |
152 | private def process(e: Element, typeValue: MyType) {
153 | typeValue.typeValue match {
154 | case x: TopLevelSimpleType => process(e, x)
155 | case x: TopLevelComplexType => process(e, x)
156 | case x: BaseType => process(e, x)
157 | }
158 | }
159 |
160 | private def process(e: Element, x: SimpleType) {
161 | visitor.simpleType(e, x)
162 | }
163 |
164 | private def process(e: Element, c: ComplexType) {
165 | c.complexTypeModelOption3.value match {
166 | case x: ComplexContent =>
167 | process(e, x)
168 | case x: SimpleContent => {
169 | val q = x.simplecontentoption.qName
170 | if (QnXsdExtension == q) {
171 | x.simplecontentoption.value match {
172 | case t: SimpleExtensionType =>
173 | process(e, t)
174 | case _ => unexpected
175 | }
176 | } else unexpected
177 | }
178 | case x: ComplexTypeModelSequence1 => {
179 | //sequence or choice
180 | process(e, x.typeDefParticleOption1.getOrElse(unexpected))
181 | }
182 | }
183 | }
184 |
185 | private def process(e: Element, x: DataRecord[TypeDefParticleOption]) {
186 | x.value match {
187 | case y: GroupRef =>
188 | unexpected
189 | case y: ExplicitGroupable =>
190 | if (x.qName == QnXsdSequence)
191 | process(e, Sequence(y))
192 | else if (x.qName == QnXsdChoice)
193 | process(e, Choice(y))
194 | else unexpected
195 | case _ => unexpected
196 | }
197 | }
198 |
199 | private def process(e: Element, cc: ComplexContent) {
200 | val q = cc.complexcontentoption.qName
201 |
202 | val value = cc.complexcontentoption.value
203 | if (QnXsdExtension == q)
204 | value match {
205 | case et: ExtensionType => {
206 | process(e, et)
207 | }
208 | case _ => unexpected
209 | }
210 | else unexpected
211 | }
212 |
213 | private def process(e: Element, et: ExtensionTypable) {
214 | extensionStack.push(et)
215 | process(e, MyType(getType(et.base)))
216 | }
217 |
218 | private def process(e: Element, x: BaseType) {
219 | visitor.baseType(e, x)
220 | }
221 |
222 | private def process(e: Element, x: Sequence) {
223 | val wrapWithSequence =
224 | extensionsIncludedInBaseSequence.isEmpty || !extensionsIncludedInBaseSequence.top
225 | if (wrapWithSequence) {
226 | visitor.startSequence(e)
227 | }
228 | val extensions = extensionStack.toList
229 | extensionStack.clear
230 | extensionsIncludedInBaseSequence.push(false)
231 | x.group.particleOption3.foreach(y => process(e, y.qName, y.value))
232 | extensionsIncludedInBaseSequence.pop
233 | extensionsIncludedInBaseSequence.push(true)
234 | extensions.foreach { y =>
235 | y.typeDefParticleOption3 match {
236 | case Some(t) => process(e, t)
237 | case None => {}
238 | }
239 | }
240 | extensionsIncludedInBaseSequence.pop
241 | if (wrapWithSequence)
242 | visitor.endSequence
243 | }
244 |
245 | private def process(e: Element, x: Choice) {
246 | val wrapWithSequence = !extensionStack.isEmpty
247 | val extensions = extensionStack.toList
248 | extensionStack.clear
249 | if (wrapWithSequence) {
250 | visitor.startSequence(e)
251 | }
252 | val anon = MyElement()
253 | val subElement = if (wrapWithSequence) anon else e
254 | visitor.startChoice(subElement, x)
255 | var index = 0
256 | extensionsIncludedInBaseSequence.push(false)
257 | x.group.particleOption3.foreach(y => {
258 | index = index + 1
259 | visitor.startChoiceItem(subElement, y.value, index)
260 | process(subElement, y.qName, y.value)
261 | visitor.endChoiceItem
262 | })
263 | extensionsIncludedInBaseSequence.pop
264 | visitor.endChoice
265 | extensionsIncludedInBaseSequence.push(true)
266 | extensions.foreach { y =>
267 | y.typeDefParticleOption3 match {
268 | case Some(t) => process(anon, t)
269 | case None => {}
270 | }
271 | }
272 | extensionsIncludedInBaseSequence.pop
273 | if (wrapWithSequence)
274 | visitor.endSequence
275 | }
276 |
277 | private def process(e: Element, q: QName, x: ParticleOption) {
278 | if (q == QnXsdElement) {
279 | x match {
280 | case y: LocalElementable => process(y)
281 | case _ => unexpected
282 | }
283 | } else if (q == QnXsdChoice) {
284 | x match {
285 | case y: ExplicitGroupable => process(e, Choice(y))
286 | case _ => unexpected
287 | }
288 | } else if (q == QnXsdSequence) {
289 | x match {
290 | case y: ExplicitGroupable => process(MyElement(), Sequence(y))
291 | case _ => unexpected
292 | }
293 | } else unexpected(q + x.toString)
294 | }
295 | }
296 |
297 | private[tree] case class MyElement(name: Option[String] = None,
298 | default: Option[String] = None, minOccurs: BigInt = BigInt(1),
299 | maxOccurs: String = "1") extends Element {
300 | val annotation: Option[xsd.Annotation] = None
301 | val elementoption: Option[scalaxb.DataRecord[xsd.ElementOption]] = None
302 | val identityConstraintOption4: Seq[scalaxb.DataRecord[xsd.IdentityConstraintOption]] = Nil
303 | val id: Option[String] = None
304 |
305 | val ref: Option[javax.xml.namespace.QName] = None
306 | val typeValue: Option[javax.xml.namespace.QName] = None
307 | val substitutionGroup: Option[javax.xml.namespace.QName] = None
308 |
309 | val fixed: Option[String] = None
310 | val nillable: Boolean = false
311 | val abstractValue: Boolean = false
312 | val finalValue: Option[String] = None
313 | val block: Option[String] = None
314 | val form: Option[xsd.FormChoice] = None
315 | val attributes: Map[String, scalaxb.DataRecord[Any]] = Map()
316 | }
317 |
318 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/resources/polrep.xsd:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | Marine Pollution Report (POLREP)
10 | ]]>
11 |
12 |
13 | PRIVACY STATEMENT
15 | The Australian Maritime Safety Authority (AMSA) is collecting the information on this form to enable it to carry out its role as managing
16 | agency of the National Plan to Combat Pollution of the Sea by Oil and other Noxious and Hazardous Substances.
17 | AMSA may give some or all of this information to other government bodies, non-government organisations who have responsibilities
18 | under the National Plan, and law enforcement agencies.
19 | ]]>
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
44 |
45 |
46 |
48 |
49 |
51 |
52 |
53 |
54 |
56 |
57 |
59 |
60 |
61 |
62 |
64 |
65 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
76 |
77 |
78 |
79 |
81 |
82 |
83 |
84 |
87 |
88 |
89 |
91 |
93 |
94 |
95 |
96 |
97 |
98 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
162 |
163 |
164 |
165 |
166 |
167 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
256 |
257 |
258 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/test/resources/australian-census-2011.xsd:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Australian Census 2011 extract
8 | ]]>
9 | Thanks for your time.
11 | ]]>
12 |
14 | ]]>
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
36 |
38 |
39 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
51 |
52 |
53 |
57 |
58 |
59 |
61 |
63 |
64 |
66 |
67 |
68 |
69 |
72 |
73 |
74 |
77 |
78 |
79 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
89 |
91 |
92 |
94 |
95 |
96 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
109 |
110 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
191 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
207 |
208 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
224 |
225 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
--------------------------------------------------------------------------------
/xsd-forms-generator/src/docs/showcase/js/xml2json.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2011-2013 Abdulla Abdurakhmanov
3 | Original sources are available at https://code.google.com/p/x2js/
4 |
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 |
9 | http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 | */
17 |
18 | function X2JS(config) {
19 | 'use strict';
20 |
21 | var VERSION = "1.1.4";
22 |
23 | config = config || {};
24 | initConfigDefaults();
25 | initRequiredPolyfills();
26 |
27 | function initConfigDefaults() {
28 | if(config.escapeMode === undefined) {
29 | config.escapeMode = true;
30 | }
31 | config.attributePrefix = config.attributePrefix || "_";
32 | config.arrayAccessForm = config.arrayAccessForm || "none";
33 | config.emptyNodeForm = config.emptyNodeForm || "text";
34 | if(config.enableToStringFunc === undefined) {
35 | config.enableToStringFunc = true;
36 | }
37 | config.arrayAccessFormPaths = config.arrayAccessFormPaths || [];
38 | if(config.skipEmptyTextNodesForObj === undefined) {
39 | config.skipEmptyTextNodesForObj = true;
40 | }
41 | if(config.stripWhitespaces === undefined) {
42 | config.stripWhitespaces = true;
43 | }
44 | }
45 |
46 | function initRequiredPolyfills() {
47 | if(typeof String.prototype.trim !== 'function') {
48 | // Hello IE8-
49 | String.prototype.trim = function() {
50 | return this.replace(/^\s+|^\n+|(\s|\n)+$/g, '');
51 | }
52 | }
53 | }
54 |
55 | var DOMNodeTypes = {
56 | ELEMENT_NODE : 1,
57 | TEXT_NODE : 3,
58 | CDATA_SECTION_NODE : 4,
59 | COMMENT_NODE : 8,
60 | DOCUMENT_NODE : 9
61 | };
62 |
63 | function getNodeLocalName( node ) {
64 | var nodeLocalName = node.localName;
65 | if(nodeLocalName == null) // Yeah, this is IE!!
66 | nodeLocalName = node.baseName;
67 | if(nodeLocalName == null || nodeLocalName=="") // =="" is IE too
68 | nodeLocalName = node.nodeName;
69 | return nodeLocalName;
70 | }
71 |
72 | function getNodePrefix(node) {
73 | return node.prefix;
74 | }
75 |
76 | function escapeXmlChars(str) {
77 | if(typeof(str) == "string")
78 | return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/');
79 | else
80 | return str;
81 | }
82 |
83 | function unescapeXmlChars(str) {
84 | return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").replace(///g, '\/');
85 | }
86 |
87 | function toArrayAccessForm(obj, childName, path) {
88 | switch(config.arrayAccessForm) {
89 | case "property":
90 | if(!(obj[childName] instanceof Array))
91 | obj[childName+"_asArray"] = [obj[childName]];
92 | else
93 | obj[childName+"_asArray"] = obj[childName];
94 | break;
95 | /*case "none":
96 | break;*/
97 | }
98 |
99 | if(!(obj[childName] instanceof Array) && config.arrayAccessFormPaths.length > 0) {
100 | var idx = 0;
101 | for(; idx < config.arrayAccessFormPaths.length; idx++) {
102 | var arrayPath = config.arrayAccessFormPaths[idx];
103 | if( typeof arrayPath === "string" ) {
104 | if(arrayPath == path)
105 | break;
106 | }
107 | else
108 | if( arrayPath instanceof RegExp) {
109 | if(arrayPath.test(path))
110 | break;
111 | }
112 | else
113 | if( typeof arrayPath === "function") {
114 | if(arrayPath(obj, childName, path))
115 | break;
116 | }
117 | }
118 | if(idx!=config.arrayAccessFormPaths.length) {
119 | obj[childName] = [obj[childName]];
120 | }
121 | }
122 | }
123 |
124 | function parseDOMChildren( node, path ) {
125 | if(node.nodeType == DOMNodeTypes.DOCUMENT_NODE) {
126 | var result = new Object;
127 | var nodeChildren = node.childNodes;
128 | // Alternative for firstElementChild which is not supported in some environments
129 | for(var cidx=0; cidx 1 && result.__text!=null && config.skipEmptyTextNodesForObj) {
211 | if( (config.stripWhitespaces && result.__text=="") || (result.__text.trim()=="")) {
212 | delete result.__text;
213 | }
214 | }
215 | delete result.__cnt;
216 |
217 | if( config.enableToStringFunc && (result.__text!=null || result.__cdata!=null )) {
218 | result.toString = function() {
219 | return (this.__text!=null? this.__text:'')+( this.__cdata!=null ? this.__cdata:'');
220 | };
221 | }
222 | return result;
223 | }
224 | else
225 | if(node.nodeType == DOMNodeTypes.TEXT_NODE || node.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) {
226 | return node.nodeValue;
227 | }
228 | }
229 |
230 | function startTag(jsonObj, element, attrList, closed) {
231 | var resultStr = "<"+ ( (jsonObj!=null && jsonObj.__prefix!=null)? (jsonObj.__prefix+":"):"") + element;
232 | if(attrList!=null) {
233 | for(var aidx = 0; aidx < attrList.length; aidx++) {
234 | var attrName = attrList[aidx];
235 | var attrVal = jsonObj[attrName];
236 | resultStr+=" "+attrName.substr(config.attributePrefix.length)+"='"+attrVal+"'";
237 | }
238 | }
239 | if(!closed)
240 | resultStr+=">";
241 | else
242 | resultStr+="/>";
243 | return resultStr;
244 | }
245 |
246 | function endTag(jsonObj,elementName) {
247 | return ""+ (jsonObj.__prefix!=null? (jsonObj.__prefix+":"):"")+elementName+">";
248 | }
249 |
250 | function endsWith(str, suffix) {
251 | return str.indexOf(suffix, str.length - suffix.length) !== -1;
252 | }
253 |
254 | function jsonXmlSpecialElem ( jsonObj, jsonObjField ) {
255 | if((config.arrayAccessForm=="property" && endsWith(jsonObjField.toString(),("_asArray")))
256 | || jsonObjField.toString().indexOf(config.attributePrefix)==0
257 | || jsonObjField.toString().indexOf("__")==0
258 | || (jsonObj[jsonObjField] instanceof Function) )
259 | return true;
260 | else
261 | return false;
262 | }
263 |
264 | function jsonXmlElemCount ( jsonObj ) {
265 | var elementsCnt = 0;
266 | if(jsonObj instanceof Object ) {
267 | for( var it in jsonObj ) {
268 | if(jsonXmlSpecialElem ( jsonObj, it) )
269 | continue;
270 | elementsCnt++;
271 | }
272 | }
273 | return elementsCnt;
274 | }
275 |
276 | function parseJSONAttributes ( jsonObj ) {
277 | var attrList = [];
278 | if(jsonObj instanceof Object ) {
279 | for( var ait in jsonObj ) {
280 | if(ait.toString().indexOf("__")== -1 && ait.toString().indexOf(config.attributePrefix)==0) {
281 | attrList.push(ait);
282 | }
283 | }
284 | }
285 | return attrList;
286 | }
287 |
288 | function parseJSONTextAttrs ( jsonTxtObj ) {
289 | var result ="";
290 |
291 | if(jsonTxtObj.__cdata!=null) {
292 | result+="";
293 | }
294 |
295 | if(jsonTxtObj.__text!=null) {
296 | if(config.escapeMode)
297 | result+=escapeXmlChars(jsonTxtObj.__text);
298 | else
299 | result+=jsonTxtObj.__text;
300 | }
301 | return result;
302 | }
303 |
304 | function parseJSONTextObject ( jsonTxtObj ) {
305 | var result ="";
306 |
307 | if( jsonTxtObj instanceof Object ) {
308 | result+=parseJSONTextAttrs ( jsonTxtObj );
309 | }
310 | else
311 | if(jsonTxtObj!=null) {
312 | if(config.escapeMode)
313 | result+=escapeXmlChars(jsonTxtObj);
314 | else
315 | result+=jsonTxtObj;
316 | }
317 |
318 | return result;
319 | }
320 |
321 | function parseJSONArray ( jsonArrRoot, jsonArrObj, attrList ) {
322 | var result = "";
323 | if(jsonArrRoot.length == 0) {
324 | result+=startTag(jsonArrRoot, jsonArrObj, attrList, true);
325 | }
326 | else {
327 | for(var arIdx = 0; arIdx < jsonArrRoot.length; arIdx++) {
328 | result+=startTag(jsonArrRoot[arIdx], jsonArrObj, parseJSONAttributes(jsonArrRoot[arIdx]), false);
329 | result+=parseJSONObject(jsonArrRoot[arIdx]);
330 | result+=endTag(jsonArrRoot[arIdx],jsonArrObj);
331 | }
332 | }
333 | return result;
334 | }
335 |
336 | function parseJSONObject ( jsonObj ) {
337 | var result = "";
338 |
339 | var elementsCnt = jsonXmlElemCount ( jsonObj );
340 |
341 | if(elementsCnt > 0) {
342 | for( var it in jsonObj ) {
343 |
344 | if(jsonXmlSpecialElem ( jsonObj, it) )
345 | continue;
346 |
347 | var subObj = jsonObj[it];
348 |
349 | var attrList = parseJSONAttributes( subObj )
350 |
351 | if(subObj == null || subObj == undefined) {
352 | result+=startTag(subObj, it, attrList, true);
353 | }
354 | else
355 | if(subObj instanceof Object) {
356 |
357 | if(subObj instanceof Array) {
358 | result+=parseJSONArray( subObj, it, attrList );
359 | }
360 | else {
361 | var subObjElementsCnt = jsonXmlElemCount ( subObj );
362 | if(subObjElementsCnt > 0 || subObj.__text!=null || subObj.__cdata!=null) {
363 | result+=startTag(subObj, it, attrList, false);
364 | result+=parseJSONObject(subObj);
365 | result+=endTag(subObj,it);
366 | }
367 | else {
368 | result+=startTag(subObj, it, attrList, true);
369 | }
370 | }
371 | }
372 | else {
373 | result+=startTag(subObj, it, attrList, false);
374 | result+=parseJSONTextObject(subObj);
375 | result+=endTag(subObj,it);
376 | }
377 | }
378 | }
379 | result+=parseJSONTextObject(jsonObj);
380 |
381 | return result;
382 | }
383 |
384 | this.parseXmlString = function(xmlDocStr) {
385 | if (xmlDocStr === undefined) {
386 | return null;
387 | }
388 | var xmlDoc;
389 | if (window.DOMParser) {
390 | var parser=new window.DOMParser();
391 | xmlDoc = parser.parseFromString( xmlDocStr, "text/xml" );
392 | }
393 | else {
394 | // IE :(
395 | if(xmlDocStr.indexOf("")==0) {
396 | xmlDocStr = xmlDocStr.substr( xmlDocStr.indexOf("?>") + 2 );
397 | }
398 | xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
399 | xmlDoc.async="false";
400 | xmlDoc.loadXML(xmlDocStr);
401 | }
402 | return xmlDoc;
403 | };
404 |
405 | this.asArray = function(prop) {
406 | if(prop instanceof Array)
407 | return prop;
408 | else
409 | return [prop];
410 | }
411 |
412 | this.xml2json = function (xmlDoc) {
413 | return parseDOMChildren ( xmlDoc );
414 | };
415 |
416 | this.xml_str2json = function (xmlDocStr) {
417 | var xmlDoc = this.parseXmlString(xmlDocStr);
418 | return this.xml2json(xmlDoc);
419 | };
420 |
421 | this.json2xml_str = function (jsonObj) {
422 | return parseJSONObject ( jsonObj );
423 | };
424 |
425 | this.json2xml = function (jsonObj) {
426 | var xmlDocStr = this.json2xml_str (jsonObj);
427 | return this.parseXmlString(xmlDocStr);
428 | };
429 |
430 | this.getVersion = function () {
431 | return VERSION;
432 | };
433 |
434 | }
435 |
--------------------------------------------------------------------------------