summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesusaves <cpntb1@ymail.com>2021-05-12 18:47:33 -0300
committerJesusaves <cpntb1@ymail.com>2021-05-12 18:47:33 -0300
commit6a343e058a776b1050773c53da583ac044df6f0f (patch)
treeb469ef551024b75aa29a1d8f3365a3c0969bb0da
parent59bc766bbbaba86d0424411f51e62778e5d37fef (diff)
downloadmessworld-tools-6a343e058a776b1050773c53da583ac044df6f0f.tar.gz
messworld-tools-6a343e058a776b1050773c53da583ac044df6f0f.tar.bz2
messworld-tools-6a343e058a776b1050773c53da583ac044df6f0f.tar.xz
messworld-tools-6a343e058a776b1050773c53da583ac044df6f0f.zip
Add CI Utils. Add Updater. And add my analysis tool (wikigen)
-rwxr-xr-xCI/imagescheck/icccheck.sh5
-rwxr-xr-xCI/imagescheck/icccheckfile.sh9
-rwxr-xr-xCI/licensecheck/checkfile.sh12
-rwxr-xr-xCI/licensecheck/clientdata.sh9
-rwxr-xr-xCI/licensecheck/serverdata.py71
-rwxr-xr-xCI/testxml/testxml.py2437
-rw-r--r--CI/testxml/xsd/XMLSchema.xsd2262
-rwxr-xr-xCI/testxml/xsd/checkfile.sh5
-rw-r--r--CI/testxml/xsd/its.xsd926
-rw-r--r--CI/testxml/xsd/tmw.xsd2117
-rw-r--r--CI/testxml/xsd/xlink.xsd79
-rw-r--r--CI/testxml/xsd/xml.xsd287
-rwxr-xr-xCI/testxml/xsdcheck.sh52
-rwxr-xr-xupdate/pseudo_update.sh31
-rwxr-xr-xwiki/wikigen.py902
15 files changed, 9204 insertions, 0 deletions
diff --git a/CI/imagescheck/icccheck.sh b/CI/imagescheck/icccheck.sh
new file mode 100755
index 0000000..6ca1481
--- /dev/null
+++ b/CI/imagescheck/icccheck.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+export DIR="../../client-data"
+
+find -H $DIR -type f -name "*.png" -exec ./icccheckfile.sh {} \;
diff --git a/CI/imagescheck/icccheckfile.sh b/CI/imagescheck/icccheckfile.sh
new file mode 100755
index 0000000..dbdfb23
--- /dev/null
+++ b/CI/imagescheck/icccheckfile.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+identify -verbose $1 | egrep -i "profile|iCCP" >/dev/null
+
+if [ "$?" == 0 ]; then
+ export name="$1"
+ export name=${name##../../client-data/}
+ echo "ICC or iCCP profile found for image $name"
+fi
diff --git a/CI/licensecheck/checkfile.sh b/CI/licensecheck/checkfile.sh
new file mode 100755
index 0000000..2de49fe
--- /dev/null
+++ b/CI/licensecheck/checkfile.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+export name="$3"
+export name=${name##../../client-data/}
+
+grep "$name" $1 >/dev/null
+if [ "$?" != 0 ]; then
+ grep "$name " $2 >/dev/null
+ if [ "$?" != 0 ]; then
+ echo "Missing license for $name"
+ fi
+fi
diff --git a/CI/licensecheck/clientdata.sh b/CI/licensecheck/clientdata.sh
new file mode 100755
index 0000000..583b197
--- /dev/null
+++ b/CI/licensecheck/clientdata.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+export DIR="../../client-data"
+
+find -H $DIR -type f -name "*.png" -exec ./checkfile.sh $DIR/LICENSE $DIR/ART_LICENSE {} \;
+find -H $DIR/sfx -type f -name "*.ogg" -exec ./checkfile.sh $DIR/LICENSE $DIR/ART_LICENSE {} \;
+find -H $DIR -type f -name "*.tmx" -exec ./checkfile.sh $DIR/LICENSE $DIR/ART_LICENSE {} \;
+find -H $DIR -type f -name "*.jpg" -exec ./checkfile.sh $DIR/LICENSE $DIR/ART_LICENSE {} \;
+
diff --git a/CI/licensecheck/serverdata.py b/CI/licensecheck/serverdata.py
new file mode 100755
index 0000000..02f4aec
--- /dev/null
+++ b/CI/licensecheck/serverdata.py
@@ -0,0 +1,71 @@
+#! /usr/bin/env python2.7
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2018 TMW-2
+# Author: Jesusalva
+
+# Bad command:
+# ls --recursive --hyperlink=always --format=single-column ../../server-data/npc/|grep txt
+
+# Initialize stuff
+import subprocess
+import sys
+import os
+erp=[]
+
+# Clear previous NPC list
+try:
+ subprocess.call("rm npcs.txt", shell=True)
+except:
+ pass
+
+# Determine correct path
+PATH="../../server-data/npc/"
+if len(sys.argv) == 2:
+ PATH=sys.argv[1]
+
+# Generate NPC list
+subprocess.call("find "+PATH+" txt > npcs.txt", shell=True)
+npcs=open("npcs.txt", "r")
+
+# Begin
+print("Checking license info for NPCs")
+print("Source is at: "+PATH)
+
+for mpa in npcs:
+ mp=mpa.replace('\n','')
+ # Skip mapflags
+ if "mapflag" in mp:
+ continue
+ # Skip bad files
+ if not '.txt' in mp:
+ continue
+ # Skip certain folders
+ if "/dev/" in mp or "/00000SAVE/" in mp or "/test/" in mp:
+ continue
+
+ a=open(mp, 'r')
+ #print("Verify %s" % mp)
+ ok=False
+ for line in a:
+ if 'tmw2 script' in line.lower() or 'tmw-2 script' in line.lower() or 'tmw 2 script' in line.lower() or 'tmw2/lof script' in line.lower() or 'This file is generated automatically' in line or 'author' in line.lower() or 'tmw2 function' in line.lower() or 'tmw-2 function' in line.lower() or 'tmw 2 function' in line.lower():
+ ok=True
+ break
+
+ a.close()
+ if not ok:
+ erp.append(mp)
+
+npcs.close()
+if len(erp) > 0:
+ print("-----------------------------------------------------------------------")
+
+for i in sorted(erp):
+ print(i)
+
+print("-----------------------------------------------------------------------")
+print("Serverdata license check result")
+print("Errors: %d" % (len(erp)))
+if len(erp):
+ os.exit(1)
+
diff --git a/CI/testxml/testxml.py b/CI/testxml/testxml.py
new file mode 100755
index 0000000..6ae9e12
--- /dev/null
+++ b/CI/testxml/testxml.py
@@ -0,0 +1,2437 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2010-2011 Evol Online
+# Author: Andrei Karas (4144)
+
+import array
+import os
+import re
+import datetime
+import xml
+import csv
+import ogg.vorbis
+import StringIO
+import sys
+from xml.dom import minidom
+from xml.etree import ElementTree
+from PIL import Image
+import zlib
+
+filt = re.compile(".+[.](xml|tmx|tsx)", re.IGNORECASE)
+filtmaps = re.compile(".+[.]tmx", re.IGNORECASE)
+filtimages = re.compile(".+[.]png", re.IGNORECASE)
+filtxmls = re.compile(".+[.]xml", re.IGNORECASE)
+filtogg = re.compile(".+[.]ogg", re.IGNORECASE)
+dyesplit1 = re.compile(";")
+dyesplit2 = re.compile(",")
+parentDir = "../../gittorious/clientdata-beta"
+iconsDir = "graphics/items/"
+spritesDir = "graphics/sprites/"
+particlesDir = "graphics/particles/"
+sfxDir = "sfx/"
+musicDir = "music/"
+mapsDir = "maps/"
+spriteErrorFile = "error.xml"
+levelUpEffectFile = "levelup.particle.xml"
+portalEffectFile = "warparea.particle.xml"
+minimapsDir = "graphics/minimaps/"
+wallpapersDir = "graphics/images/"
+wallpaperFile = "login_wallpaper.png"
+
+errors = 0
+warnings = 0
+errDict = set()
+safeDye = False
+borderSize = 14 # Required 18 # Original 14
+tiledVersion = 13 # Minimum Tiled version, advised "14" for Tiled 1.4
+colorsList = set()
+showAll = False
+silent = False
+stfu = False
+herc = False
+
+testBadCollisions = False
+# number of tiles difference. after this amount tiles can be counted as incorrect
+tileNumDiff = 3
+# max number of incorrect tiles. If more then tile not counted as error
+maxNumErrTiles = 5
+
+class Tileset:
+ None
+
+class Layer:
+ None
+
+def printErr(err):
+ errDict.add(err)
+ print err.encode("utf-8")
+
+def showFileErrorById(id, rootDir, fileDir):
+ rootDir = rootDir.encode("utf-8")
+ fileDir = fileDir.encode("utf-8")
+ print "error: id=" + id + ", file not found: " + fileDir + " (" + rootDir + fileDir + ")"
+
+def showFileWarningById(id, rootDir, fileDir):
+ rootDir = rootDir.encode("utf-8")
+ fileDir = fileDir.encode("utf-8")
+ print "warn: id=" + id + ", file not found: " + fileDir + " (" + rootDir + fileDir + ")"
+
+def showError(id, text):
+ text = text.encode("utf-8")
+ print "error: id=" + id + " " + text
+
+def showWarning(id, text):
+ text = text.encode("utf-8")
+ print "warn: id=" + id + " " + text
+
+def showMsg(id, text, src, iserr):
+ global errors, warnings
+ if text != "":
+ text = text + ", " + src
+ if iserr == True:
+ if text not in errDict:
+ showError(id, text)
+ errDict.add(text)
+ errors = errors + 1
+ else:
+ if text not in errDict:
+ showWarning(id, text)
+ errDict.add(text)
+ warnings = warnings + 1
+
+def showMsgSprite(file, text, iserr):
+ global errors, warnings
+ if iserr == True:
+ err = "error: sprite=" + file + " " + text
+ if err not in errDict:
+ printErr(err)
+ errors = errors + 1
+ else:
+ err = "warn: sprite=" + file + " " + text
+ if err not in errDict:
+ printErr(err)
+ warnings = warnings + 1
+
+def showMsgFile(file, text, iserr):
+ global errors, warnings
+ if iserr == True:
+ err = "error: file=" + file + " " + text
+ if err not in errDict:
+ printErr(err)
+ errors = errors + 1
+ else:
+ err = "warn: file=" + file + " " + text
+ if err not in errDict:
+ printErr(err)
+ warnings = warnings + 1
+
+def showFileMsgById(id, rootDir, fileDir, iserr):
+ global errors, warnings
+ if iserr == True:
+ showFileErrorById(id, rootDir, fileDir)
+ errors = errors + 1
+ else:
+ showFileWarningById(id, rootDir, fileDir)
+ warnings = warnings + 1
+
+def printSeparator():
+ print "--------------------------------------------------------------------------------"
+
+def showHeader():
+ print "Evol client data validator."
+ print "Run at: " + datetime.datetime.now().isoformat()
+ print "https://gitlab.com/evol/evol-tools/blob/master/testxml/testxml.py"
+ printSeparator()
+
+def showFooter():
+ printSeparator()
+ print "Total:"
+ print " Warnings: " + str(warnings)
+ print " Errors: " + str(errors)
+
+def enumDirs(parentDir):
+ global warnings, errors
+ try:
+ files = os.listdir(parentDir)
+ except OSError:
+ print "Directory error: " + parentDir
+ if silent == False:
+ warnings = warnings + 1
+ return
+ for file1 in files:
+ if file1[0] == ".":
+ continue
+ file2 = os.path.abspath(parentDir + os.path.sep + file1)
+ if not os.path.isfile(file2):
+ enumDirs(file2)
+ else:
+ if filt.search(file1):
+ try:
+ if silent == True and not stfu:
+ print "Checking " + file2
+ minidom.parse(file2)
+ except xml.parsers.expat.ExpatError as err:
+ print "error: " + file2 + ", line=" + str(err.lineno) + ", char=" + str(err.offset)
+ errors = errors + 1
+ if file1 != "testxml.py":
+ checkFilePermission(file2)
+
+def checkFilePermission(fullName):
+ global warnings
+ if os.access(fullName, os.X_OK):
+ print "warn: execute flag on file: " + fullName
+ warnings = warnings + 1
+
+
+def loadPaths():
+ global warnings, iconsDir, spritesDir, sfxDir, particlesDir, mapsDir, spriteErrorFile, \
+ levelUpEffectFile, portalEffectFile, minimapsDir, wallpapersDir, walpaperFile, \
+ musicDir, wallpaperFile
+ try:
+ dom = minidom.parse(parentDir + "/paths.xml")
+ for node in dom.getElementsByTagName("option"):
+ if node.attributes["name"].value == "itemIcons":
+ iconsDir = node.attributes["value"].value
+ if iconsDir != "graphics/items/":
+ print "warn: itemIcons path has not default value."\
+ " Will be incampatible with old clients."
+ warnings = warnings + 1
+ elif node.attributes["name"].value == "sprites":
+ spritesDir = node.attributes["value"].value
+ if spritesDir != "graphics/sprites/":
+ print "warn: sprites path has not default value."\
+ " Will be incampatible with old clients."
+ warnings = warnings + 1
+ elif node.attributes["name"].value == "sfx":
+ sfxDir = node.attributes["value"].value
+
+ elif node.attributes["name"].value == "particles":
+ particlesDir = node.attributes["value"].value
+ if particlesDir != "graphics/particles/":
+ print "warn: particles path has not default value."\
+ " Will be incampatible with old clients."
+ warnings = warnings + 1
+ elif node.attributes["name"].value == "maps":
+ mapsDir = node.attributes["value"].value
+ if mapsDir != "maps/":
+ print "warn: maps path has not default value."\
+ " Will be incampatible with old clients."
+ warnings = warnings + 1
+ elif node.attributes["name"].value == "spriteErrorFile":
+ spriteErrorFile = node.attributes["value"].value
+ elif node.attributes["name"].value == "levelUpEffectFile":
+ levelUpEffectFile = node.attributes["value"].value
+ elif node.attributes["name"].value == "portalEffectFile":
+ portalEffectFile = node.attributes["value"].value
+ elif node.attributes["name"].value == "minimaps":
+ minimapsDir = node.attributes["value"].value
+ elif node.attributes["name"].value == "wallpapers":
+ wallpapersDir = node.attributes["value"].value
+ elif node.attributes["name"].value == "wallpaperFile":
+ wallpaperFile = node.attributes["value"].value
+ elif node.attributes["name"].value == "music":
+ musicDir = node.attributes["value"].value
+
+ except:
+ print "warn: paths.xml not found"
+ warnings = warnings + 1
+
+def splitImage(image):
+ try:
+ idx = image.find("|")
+ if idx > 0:
+ imagecolor = image[idx + 1:]
+ image = image[0:idx]
+ else:
+ imagecolor = ""
+ except:
+ image = ""
+ imagecolor = ""
+ return [image, imagecolor]
+
+def testDye(id, color, text, src, iserr):
+ if len(color) < 4:
+ showMsg(id, "dye to small size: " + text, src, iserr)
+ return
+ colors = dyesplit1.split(color)
+ for col in colors:
+ if len(col) < 4:
+ showMsg(id, "dye to small size: " + text, src, iserr)
+ continue
+
+ c = col[0];
+ if col[1] != ":":
+ showMsg(id, "incorrect dye string: " + text, src, iserr)
+ continue
+
+ if c != "R" and c != "G" and c != "B" and c != "Y" and c != "M" \
+ and c != "C" and c != "W" and c != "S":
+ showMsg(id, "incorrect dye color: " + c + " in " + text, src, iserr)
+ continue
+ if testDyeInternal(id, col[2:], text, src, iserr) == False:
+ continue
+
+
+def testDyeInternal(id, col, text, src, iserr):
+ oldPalette = col[0] == "#"
+ if oldPalette == False and col[0] != "@":
+ showMsg(id, "incorrect dye colors: " + text, src, iserr)
+ return False
+
+ if oldPalette:
+ paletes = dyesplit2.split(col[1:])
+ for palete in paletes:
+ if len(palete) != 6:
+ showMsg(id, "incorrect dye palete: " + text, src, iserr)
+ return False
+
+ for char in palete.lower():
+ if (char < '0' or char > '9') and (char < 'a' or char > 'f'):
+ showMsg(id, "incorrect dye palete: " + text, src, iserr)
+ return False
+ return True
+
+
+def testDyeColors(id, color, text, src, iserr):
+ if len(color) < 4:
+ showMsg(id, "dye to small size: " + text, src, iserr)
+ return -1
+ colors = dyesplit1.split(color)
+ for col in colors:
+ if len(col) < 4:
+ showMsg(id, "dye to small size: " + text, src, iserr)
+ continue
+ if testDyeInternal(id, col, text, src, iserr) == False:
+ continue
+ return len(colors)
+
+def testDyeChannel(file, color, text, iserr):
+ if len(color) < 1:
+ showMsgSprite(file, "dye channel size to small:" + text, iserr)
+ return -1
+ colors = dyesplit1.split(color)
+ for c in colors:
+ if len(c) != 1:
+ showMsgSprite(file, "dye channel incorrect size: " + text, iserr)
+ continue
+ if c != "R" and c != "G" and c != "B" and c != "Y" and c != "M" \
+ and c != "C" and c != "W" and c != "S":
+ showMsgSprite(file, "dye make incorrect: " + text, iserr)
+ continue
+ return len(colors)
+
+
+def testSprites(id, node, checkGender, isNormalDye, isMust, checkAction, iserr):
+ try:
+ tmp = node.getElementsByTagName("nosprite")
+ if tmp is not None and len(tmp) > 1:
+ showMsg(id, "more than one nosprite tag found", "", iserr)
+ nosprite = True
+ except:
+ nosprite = False
+
+ if isMust == False:
+ nosprite = True
+
+ try:
+ sprites = node.getElementsByTagName("sprite")
+ except:
+ sprites = None
+ if nosprite == False:
+ showMsg(id, "no sprite tag found", "", iserr)
+
+ if sprites is not None:
+ if len(sprites) == 0 or len(sprites[0].childNodes) == 0:
+ if nosprite == False:
+ showMsg(id, "no sprite tags found", "", iserr)
+ elif len(sprites) > 3 and checkGender:
+ showMsg(id, "incorrect number of sprite tags", "", iserr)
+ elif len(sprites) == 1:
+ file = sprites[0].childNodes[0].data
+ if checkGender:
+ try:
+ gender = sprites[0].attributes["gender"].value
+ except:
+ gender = ""
+
+ if gender != "" and gender != "unisex":
+ showMsg(id, "gender tag in alone sprite", "", iserr)
+
+ try:
+ variant = int(sprites[0].attributes["variant"].value)
+ except:
+ variant = 0
+
+ testSprite(id, file, variant, isNormalDye, checkAction, iserr)
+ else:
+ male = False
+ female = False
+ unisex = False
+ for sprite in sprites:
+ file = sprite.childNodes[0].data
+ if checkGender:
+ try:
+ gender = sprite.attributes["gender"].value
+ except:
+ gender = ""
+ if gender == "male":
+ if male == True:
+ showMsg(id, "double male sprite tag", "", iserr)
+ male = True
+ elif gender == "female":
+ if female == True:
+ showMsg(id, "double female sprite tag", "", iserr)
+ female = True
+ elif gender == "unisex":
+ unisex = True
+ try:
+ variant = int(sprite.attributes["variant"].value)
+ except:
+ variant = 0
+ testSprite(id, file, variant, isNormalDye, checkAction, iserr)
+ if checkGender:
+ if male == False and unisex == False:
+ showMsg(id, "no male sprite tag", "",iserr)
+ if female == False and unisex == False:
+ showMsg(id, "no female sprite tag", "", iserr)
+ if unisex == True and female == True and male == True:
+ showMsg(id, "gender sprite tag with unisex tag", "", iserr)
+ if unisex == False and male == False and female == False:
+ showMsg(id, "no any gender tags", "", iserr)
+
+def testSprite(id, file, variant, isNormalDye, checkAction, iserr):
+ global safeDye
+ tmp = splitImage(file)
+ color = tmp[1]
+ file2 = tmp[0]
+ if color != "":
+ dnum = testDyeColors(id, color, file, "", iserr)
+ else:
+ dnum = 0
+
+ fullPath = os.path.abspath(parentDir + "/" + spritesDir + file2)
+ if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False:
+ showFileMsgById(id, spritesDir, file2, iserr)
+ else:
+ if not isNormalDye and color is not None and len(color) > 0:
+ showMsg(id, "sprite tag have dye string but it should not, because used colors dye", color, iserr)
+
+ oldSafe = safeDye
+ safeDye = True
+ testSpriteFile(id, fullPath, file, spritesDir + file2, dnum, variant, checkAction, iserr)
+ safeDye = oldSafe
+
+def powerOfTwo(num):
+ val = 1
+ while val < num:
+ val = val * 2
+ return val
+
+def testSpriteFile(id, fullPath, file, fileLoc, dnum, variant, checkAction, iserr):
+ global safeDye
+
+ try:
+ dom = minidom.parse(fullPath)
+ except:
+ return
+
+ if len(dom.childNodes) < 1:
+ return
+
+ try:
+ variants = dom.documentElement.attributes["variants"].value
+ except:
+ variants = 0
+
+# try:
+# variant_offset = dom.documentElement.attributes["variant_offset"].value
+# except:
+# variant_offset = 0
+
+# root = dom.childNodes[0];
+ imagesets = dom.getElementsByTagName("imageset")
+ if imagesets is None or len(imagesets) < 1:
+ showMsgSprite(fileLoc, "incorrect number of imageset tags", iserr)
+ return
+ isets = set()
+ imagesetnums = dict()
+ num = 0
+ for imageset in imagesets:
+ try:
+ name = imageset.attributes["name"].value
+ except:
+ showMsgSprite(fileLoc, "imageset don't have name attribute", iserr)
+ name = None
+
+ if name is not None:
+ if name in isets:
+ showMsgSprite(fileLoc, "imageset with name '" + name + "' already exists", iserr)
+ isets.add(name)
+
+ image = ""
+ try:
+ image = imageset.attributes["src"].value
+ image0 = image
+ img = splitImage(image)
+ image = img[0]
+ imagecolor = img[1]
+ except:
+ showMsgSprite(fileLoc, "image attribute not exist: " + image, iserr)
+ continue
+
+ try:
+ width = imageset.attributes["width"].value
+ except:
+ showMsgSprite(fileLoc, "no width attribute", iserr)
+ continue
+
+ try:
+ height = imageset.attributes["height"].value
+ except:
+ showMsgSprite(fileLoc, "no height attribute", iserr)
+
+ if imagecolor != "":
+ num = testDyeChannel(fileLoc, imagecolor, image0, iserr)
+ if safeDye == False and dnum != num:
+ if dnum > num:
+ e = iserr
+ else:
+ e = False
+ showMsgSprite(fileLoc, "dye colors size not same in sprite (" + str(num) \
+ + ") and in caller (" + str(dnum) + ", id=" + str(id) + ")", e)
+ elif safeDye == True and dnum > 0:
+ showMsgSprite(fileLoc, "dye set in sprite but not in caller (id=" + str(id) + ")", False)
+
+
+ fullPath = os.path.abspath(parentDir + "/" + image)
+ if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False:
+ showMsgSprite(fileLoc, "image file not exist: " + image, iserr)
+ continue
+ sizes = testImageFile(image, fullPath, 0, " " + fileLoc, iserr)
+ s1 = int(sizes[0] / int(width)) * int(width)
+
+ sizesOGL = [0,1]
+ sizesOGL[0] = powerOfTwo(sizes[0])
+ sizesOGL[1] = powerOfTwo(sizes[1])
+
+ if s1 == 0:
+ tmp = int(width)
+ else:
+ tmp = s1
+ if sizes[0] != s1 and tmp != sizesOGL[0] and sizes[0] != sizesOGL[0]:
+ if silent != True:
+ showMsgSprite(fileLoc, "image width " + str(sizes[0]) + \
+ " (need " + str(tmp) + ") is not multiply to frame size " + width + ", image:" + image, False)
+
+ if sizes[0] != sizesOGL[0]:
+ if sizesOGL[0] > sizes[0]:
+ txt = str(sizesOGL[0] / 2) + " or "
+ else:
+ txt = ""
+
+ if showAll is True:
+ showMsgSprite(fileLoc, "image width should be power of two. If not image will be resized on the fly."\
+ "\nCurrent image width " + str(sizes[0]) + \
+ ". used in sprite width " + str(tmp) +
+ "\nallowed width " + txt + str(sizesOGL[0]) + " (" + image + ")", False)
+
+ s2 = int(sizes[1] / int(height)) * int(height)
+
+ if s2 == 0:
+ tmp = int(height)
+ else:
+ tmp = s2;
+
+ if sizes[1] != s2 and tmp != sizesOGL[1] and sizes[1] != sizesOGL[1]:
+ if silent != True:
+ showMsgSprite(fileLoc, "image height " + str(sizes[1]) + \
+ " (need " + str(tmp) + ") is not multiply to frame size " + height + ", image:" + image, False)
+
+ if sizes[1] != sizesOGL[1]:
+ if sizesOGL[1] > sizes[1]:
+ txt = str(sizesOGL[1] / 2) + " or "
+ else:
+ txt = ""
+
+ if showAll is True:
+ showMsgSprite(fileLoc, "image height should be power of two. If not image will be resized on the fly."\
+ "\nCurrent image height " + str(sizes[1]) + \
+ ". used in sprite height " + str(tmp) +
+ "\nallowed height " + txt + str(sizesOGL[1]) + " (" + image + ")", False)
+
+
+ num = (s1 / int(width)) * (s2 / int(height))
+ if variants == 0 and variant > 0:
+ showMsgSprite(fileLoc, "missing variants attribute in sprite", iserr)
+ if variants > 0 and variant >= variants:
+ showMsgSprite(fileLoc, "variant number more then in variants attribute", iserr)
+
+ if variant > 0 and variant >= num:
+ showMsgSprite(fileLoc, "to big variant number " + str(variant) \
+ + ". Frames number " + str(num) + ", id=" + str(id), iserr)
+ if num < 1:
+ showMsgSprite(fileLoc, "image have zero frames: " + image, iserr)
+ if name is not None and num > 0:
+ imagesetnums[name] = num
+
+ try:
+ includes = dom.getElementsByTagName("include")
+ for include in includes:
+ try:
+ incfile = include.attributes["file"].value
+ file2 = os.path.abspath(parentDir + os.path.sep + spritesDir + incfile)
+ if not os.path.isfile(file2):
+ showMsgSprite(fileLoc, "include file not exists " + incfile, True)
+ except:
+ showMsgSprite(fileLoc, "bad include", iserr)
+
+
+ except:
+ includes = None
+
+ #todo need parse included files
+
+ try:
+ actions = dom.getElementsByTagName("action")
+ except:
+ actions = None
+
+ if (actions == None or len(actions) == 0) and (includes == None or len(includes) == 0):
+ showMsgSprite(fileLoc, "no actions in sprite file", iserr)
+ else:
+ actset = set()
+ frameSet = set()
+ hpSet = set()
+ for action in actions:
+ try:
+ name = action.attributes["name"].value
+ except:
+ showMsgSprite(fileLoc, "no action name", iserr)
+ continue
+ try:
+ hp = action.attributes["hp"].value
+ except:
+ hp = "100"
+ try:
+ setname = action.attributes["imageset"].value
+ except:
+ setname = ""
+ if setname in imagesetnums:
+ num = imagesetnums[setname]
+ else:
+ num = 0
+ showMsgSprite(fileLoc, "using incorrect imageset name in action: " + name, iserr)
+ frameSet = frameSet | testSpriteAction(fileLoc, name, action, num, iserr)
+
+ if name + "|" + hp in actset:
+ showMsgSprite(fileLoc, "duplicate action: " + name, iserr)
+ continue
+ actset.add(name + "|" + hp)
+ hpSet.add(hp)
+
+ if len(frameSet) > 0:
+ errIds = ""
+ i = 0
+ while i < max(frameSet):
+ if i not in frameSet:
+ errIds = errIds + str(i) + ","
+ i = i + 1
+ if len(errIds) > 0:
+ if silent != True:
+ showMsgSprite(fileLoc, "unused frames: " + errIds[0:len(errIds)-1], False)
+
+ if checkAction != "":
+ for hp in hpSet:
+ if checkAction + "|" + hp not in actset:
+ showMsgSprite(fileLoc, "no attack action '" + checkAction + "' in sprite", iserr)
+
+
+def testSpriteAction(file, name, action, numframes, iserr):
+ framesid = set()
+
+ try:
+ animations = action.getElementsByTagName("animation")
+ except:
+ animations = None
+
+ if animations == None or len(animations) == 0:
+ if name != "default":
+ showMsgSprite(file, "no animation tags in action: " + name, False)
+ else:
+ return framesid
+
+ aniset = set()
+ delayTags = ("frame", "sequence", "pause")
+
+ for animation in animations:
+ lastAttack = None
+ try:
+ direction = animation.attributes["direction"].value
+ except:
+ direction = "default"
+
+ if direction is aniset:
+ showMsgSprite(file, "duplicate direction in action: " + name, iserr)
+ continue
+ aniset.add(direction)
+
+ lastIndex1 = -1
+ lastIndex2 = -1
+ lastOffsetX = 0
+ lastOffsetY = 0
+ cnt = 0
+ labels = set()
+
+ for node2 in animation.childNodes:
+ if name == "attack" and node2.nodeName != "#text":
+ lastAttack = node2.nodeName
+ if node2.nodeName in delayTags:
+ try:
+ delay = int(node2.attributes["delay"].value)
+ except:
+ delay = 0
+
+ if delay % 10 != 0 and showAll is True:
+ showMsgSprite(file, "delay " + str(delay) + " must be multiple of 10 in action: " + name + \
+ ", direction: " + direction, False)
+
+
+ if node2.nodeName == "frame" or node2.nodeName == "sequence":
+ try:
+ offsetX = int(node2.attributes["offsetX"].value)
+ except:
+ offsetX = 0
+ try:
+ offsetY = int(node2.attributes["offsetY"].value)
+ except:
+ offsetY = 0
+
+ if node2.nodeName == "frame":
+ frame = node2
+ try:
+ idx = int(frame.attributes["index"].value)
+ except:
+ showMsgSprite(file, "no frame index in action: " + name, iserr)
+
+ if idx >= numframes or idx < 0:
+ showMsgSprite(file, "incorrect frame index " + str(idx) + \
+ " action: " + name + ", direction: "\
+ + direction, iserr)
+ else:
+ framesid.add(idx)
+ if lastIndex1 == idx and lastIndex2 == -1 and offsetX == lastOffsetX \
+ and offsetY == lastOffsetY:
+ showMsgSprite(file, "duplicate frame animation for frame index=" \
+ + str(idx) + " action: " + name + \
+ ", direction: " + direction + "\n" + node2.toxml(), False)
+ #print node2.toxml()
+ else:
+ lastIndex1 = idx
+ lastIndex2 = -1
+ lastOffsetX = offsetX
+ lastOffsetY = offsetY
+
+ framesid.add(idx)
+ cnt = cnt + 1
+ elif node2.nodeName == "sequence":
+ sequence = node2
+ try:
+ sframes = dyesplit2.split(sequence.attributes["value"].value)
+ except:
+ sframes = None
+ if sframes is not None:
+ for frm in sframes:
+ if frm != "p":
+ k = frm.find("-")
+ if k == 0 or k == len(frm) - 1:
+ showMsgSprite(file, "incorrect sequence value " + \
+ name + ", direction: " + direction, iserr)
+ elif k == -1:
+ #same as frame
+ idx = int(frm)
+ if idx >= numframes or idx < 0:
+ showMsgSprite(file, "incorrect frame index " + str(idx) + \
+ " action: " + name + ", direction: "\
+ + direction, iserr)
+ else:
+ framesid.add(idx)
+ else:
+ #same as simple sequence
+ i1 = int(frm[:k])
+ i2 = int(frm[k + 1:])
+ if i1 >= numframes or i1 < 0:
+ showMsgSprite(file, "incorrect start sequence index " + str(i1) + \
+ " action: " + name + ", direction: " + direction, iserr)
+ if i2 >= numframes or i2 < 0:
+ showMsgSprite(file, "incorrect end sequence index " + str(i2) + \
+ " action: " + name + ", direction: " + direction, iserr)
+ if i1 == i2:
+ showMsgSprite(file, "start and end sequence index is same. " \
+ + "May be better use frame? action: " + \
+ name + ", direction: " + direction, False)
+
+ for i in range(i1,i2 + 1):
+ framesid.add(i)
+ cnt = cnt + 1
+ continue
+
+ try:
+ i1 = int(sequence.attributes["start"].value)
+ i2 = int(sequence.attributes["end"].value)
+ except:
+ showMsgSprite(file, "no sequence start or end index action: " + \
+ name + ", direction: " + direction, iserr)
+# try:
+# repeat = int(sequence.attributes["repeat"].value)
+# except:
+# repeat = 1
+
+ if i1 >= numframes or i1 < 0:
+ showMsgSprite(file, "incorrect start sequence index " + str(i1) + \
+ " action: " + name + ", direction: " + direction, iserr)
+ if i2 >= numframes or i2 < 0:
+ showMsgSprite(file, "incorrect end sequence index " + str(i2) + \
+ " action: " + name + ", direction: " + direction, iserr)
+ if i1 == i2:
+ showMsgSprite(file, "start and end sequence index is same. " \
+ + "May be better use frame? action: " + \
+ name + ", direction: " + direction, False)
+
+ if lastIndex1 == i1 and lastIndex2 == i2 and offsetX == lastOffsetX \
+ and offsetY == lastOffsetY:
+ showMsgSprite(file, "duplicate sequence animation. May be need use repeat attribue? for start=" \
+ + str(i1) + ", end=" + str(i2) + " action: " + \
+ name + ", direction: " + direction + "\n" + node2.toxml(), False)
+ else:
+ lastIndex1 = i1
+ lastIndex2 = i2
+ lastOffsetX = offsetX
+ lastOffsetY = offsetY
+
+ cnt = cnt + 1
+ for i in range(i1,i2 + 1):
+ framesid.add(i)
+ elif node2.nodeName == "end" or node2.nodeName == "jump" or node2.nodeName == "label" or node2.nodeName == "goto":
+ lastIndex1 = -1
+ lastIndex2 = -1
+ lastOffsetX = 0
+ lastOffsetY = 0
+ cnt = cnt + 1
+ elif node2.nodeName == "pause":
+ try:
+ delay = int(node2.attributes["delay"].value)
+ except:
+ delay = 0
+ if delay <= 0:
+ showMsgSprite(file, "incorrect delay in pause tag " + name, iserr)
+
+ elif node2.nodeName == "#text" or node2.nodeName == "#comment":
+ None
+ else:
+ showMsgSprite(file, "unknown animation tag: " + node2.nodeName + ", " + name, False)
+
+ if node2.nodeName == "jump":
+ try:
+ jaction = node2.attributes["action"].value
+ except:
+ jaction = ""
+ if jaction == "" or jaction is None:
+ showMsgSprite(file, "no action attribute in jump tag " + name, iserr)
+ elif node2.nodeName == "label":
+ try:
+ label = node2.attributes["name"].value
+ except:
+ label = ""
+ if label == "" or label is None:
+ showMsgSprite(file, "no name attribute in label tag " + name, iserr)
+ else:
+ if label in labels:
+ showMsgSprite(file, "duplicate label " + label + " " + name + "\n" \
+ + node2.toxml(), iserr)
+ else:
+ labels.add(label)
+ elif node2.nodeName == "goto":
+ try:
+ label = node2.attributes["label"].value
+ except:
+ label = ""
+ if label == "" or label is None:
+ showMsgSprite(file, "no label attribute in goto tag " + name, iserr)
+ if cnt == 0:
+ showMsgSprite(file, "no frames or sequences in action: " + name, iserr)
+
+ if name == "attack":
+ if lastAttack is not None and lastAttack != "end":
+ showMsgSprite(file, "last attack tag should be <end/> or attack animation "\
+ "can be infinite. direction: " + direction, False)
+
+
+ if "default" not in aniset:
+ if "down" not in aniset:
+ showMsgSprite(file, "no down direction in animation: " + name, iserr)
+ if "up" not in aniset:
+ showMsgSprite(file, "no up direction in animation: " + name, iserr)
+ if "left" not in aniset:
+ showMsgSprite(file, "no left direction in animation: " + name, iserr)
+ if "right" not in aniset:
+ showMsgSprite(file, "no right direction in animation: " + name, iserr)
+
+ if name == "dead" and len(animations) > 0:
+ lastani = animations[len(animations) - 1]
+ lastNode = None
+ nc = 0
+ for node in lastani.childNodes:
+ if node.nodeName == "frame":
+ lastNode = node
+ nc = nc + 1
+ if node.nodeName == "sequence":
+ lastNode = node
+ nc = nc + 2
+ if nc > 1:
+ try:
+ cont = int(lastNode.attributes["continue"].value)
+ except:
+ cont = 0;
+ if cont == 0:
+ try:
+ delay = int(lastNode.attributes["delay"].value)
+ except:
+ delay = 0
+ if delay > 0 and delay < 5000:
+ showMsgSprite(file, "last frame\sequence in dead animation have to low limit. Need zero or >5000: " + name, False)
+
+ return framesid
+
+
+def testImageFile(file, fullPath, sz, src, iserr):
+ try:
+ img = Image.open(fullPath, "r")
+ img.load()
+ except:
+ showMsgFile(file, "incorrect image format" + src, iserr)
+ return
+
+ if img.format != "PNG":
+ showMsgFile(file, "image format is not png" + src, False)
+
+ sizes = img.size
+ if sz != 0:
+ if sizes[0] > sz or sizes[1] > sz:
+ showMsgFile(file, "image size incorrect (" + str(sizes[0]) \
+ + "x" + str(sizes[1]) + ") should be (" + str(sz) + "x" \
+ + str(sz) + ")", iserr)
+ elif sizes[0] < sz or sizes[1] < sz:
+ showMsgFile(file, "possible image size incorrect (" + str(sizes[0]) \
+ + "x" + str(sizes[1]) + ") should be (" + str(sz) + "x" \
+ + str(sz) + ")", False)
+
+ return sizes
+
+def testSound(file, sfxDir, msg):
+ fullPath = parentDir + "/" + sfxDir + file
+ if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False:
+ print "error:" + fullPath
+ if msg != "":
+ showMsgFile(file, "sound file not found: " + msg , True)
+ else:
+ showMsgFile(file, "sound file not found", True)
+ return
+ try:
+ ogg.vorbis.VorbisFile(fullPath)
+ except ogg.vorbis.VorbisError as e:
+ showMsgFile(file, "sound file incorrect error: " + str(e), True)
+
+
+def testParticle(id, file, src):
+ fullPath = parentDir + "/" + file
+ if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False:
+ showMsgFile(file, "particle file not found", True)
+ return
+ try:
+ dom = minidom.parse(fullPath)
+ except:
+ showMsgFile(file, "incorrect particle xml file", True)
+ return
+
+ nodes = dom.getElementsByTagName("particle")
+ if len(nodes) < 1:
+ showMsgFile(file, "missing particle tags", False)
+ else:
+ for node in nodes:
+ testEmitters(id, file, node, file)
+
+
+def testEmitters(id, file, parentNode, src):
+ for node in parentNode.getElementsByTagName("property"):
+ try:
+ name = node.attributes["name"].value
+ except:
+ showMsgFile(file, "missing attribute name in emitter" \
+ " in particle file", True)
+ continue
+ try:
+ value = node.attributes["value"].value
+ except:
+ value = None
+
+ if name == "image":
+ if value == None:
+ showMsgFile(file, "missing attribute value in emitter" \
+ " image attribute", True)
+ img = splitImage(value)
+ image = img[0]
+ imagecolor = img[1]
+ if imagecolor != None and len(imagecolor) > 0:
+ testDye(id, imagecolor, "image=" + image, src, True)
+ fullName = parentDir + "/" + image
+ if not os.path.isfile(fullName) or os.path.exists(fullName) == False:
+ showMsgFile(file, "image file not exist: " + image, True)
+ else:
+ testImageFile(image, fullName, 0, " " + file,True)
+ for node in parentNode.getElementsByTagName("emitter"):
+ testEmitters(id, file, node, src)
+
+
+
+def testItems(fileName, imgDir):
+ global warnings, errors, safeDye
+ if not stfu:
+ print "Checking " + fileName
+ try:
+ dom = minidom.parse(parentDir + "/" + fileName)
+ except Exception as err:
+ print "error: " + fileName + ": corrupted"
+ print err
+ errors = errors + 1
+ return
+ idset = set()
+ oldId = None
+ for node in dom.documentElement.childNodes:
+ if node.nodeName == "include":
+ try:
+ name = node.attributes["name"].value
+ if name == "":
+ errors = errors + 1
+ print "error: " + fileName + ": Empty include name";
+ testItems(name, imgDir)
+ except:
+ errors = errors + 1
+ print "error: " + fileName + ": Broken include tag";
+ continue
+ if node.nodeName != "item":
+ continue
+
+ if node.parentNode != dom.documentElement:
+ continue
+
+ try:
+ id = node.attributes["id"].value
+ except:
+ if oldId is None:
+ print "error: " + fileName + ": item without id"
+ else:
+ print "error: " + fileName + ": item without id. Last id was: " + oldId
+ errors = errors + 1
+ continue
+ oldId = id
+ if id in idset:
+ print "error: " + fileName + ": duplicated id=" + id
+ errors = errors + 1
+ else:
+ idset.add(id)
+
+ idI = int(id)
+
+ try:
+ colors = node.attributes["colors"].value
+ except:
+ colors = None
+
+ try:
+ type = node.attributes["type"].value
+ except:
+ type = ""
+ print "warn: " + fileName + ": no type attribute for id=" + id
+ warnings = warnings + 1
+ try:
+ image = node.attributes["image"].value
+ image0 = image
+ img = splitImage(image)
+ image = img[0]
+ imagecolor = img[1]
+ except:
+ image = ""
+ image0 = ""
+ imagecolor = ""
+
+ try:
+ floor = node.attributes["floor"].value
+ floor0 = floor
+ flr = splitImage(floor)
+ floor = flr[0]
+ floorcolor = flr[1]
+ except:
+ floor = None
+ floor0 = None
+ floorcolor = None
+
+ try:
+ description = node.attributes["description"].value
+ except:
+ description = ""
+
+ try:
+ missile = node.attributes["missile-particle"].value
+ except:
+ missile = ""
+
+ try:
+ drawBefore = node.attributes["drawBefore"].value
+ except:
+ drawBefore = ""
+
+ try:
+ drawAfter = node.attributes["drawAfter"].value
+ except:
+ drawAfter = ""
+
+# try:
+# drawPriority = int(node.attributes["drawPriority"].value)
+# except:
+# drawPriority = 0
+
+ if type == "hairsprite":
+ if idI >= 0:
+ print "error: " + fileName + ": hairsprite with id=" + id
+ errors = errors + 1
+ elif idI < -100:
+ print "error: " + fileName + ": hairsprite override player sprites"
+ errors = errors + 1
+
+ safeDye = True
+ testSprites(id, node, True, True, True, "", True)
+ safeDye = False
+
+ elif type == "racesprite":
+ if idI >= 0:
+ print "error: " + fileName + ": racesprite with id=" + id
+ errors = errors + 1
+ elif idI > -100:
+ print "error: " + fileName + ": racesprite override player hair"
+ errors = errors + 1
+ elif type == "usable" or type == "unusable" or type == "generic" \
+ or type == "equip-necklace" or type == "equip-torso" or type == "equip-feet" \
+ or type == "equip-arms" or type == "equip-legs" or type == "equip-head" \
+ or type == "equip-shield" or type == "equip-1hand" or type == "equip-2hand" \
+ or type == "equip-charm" or type == "equip-ammo" or type == "equip-neck" \
+ or type == "equip-ring" or type == "card":
+ if image == "":
+ print "error: " + fileName + ": missing image attribute on id=" + id
+ errors = errors + 1
+ continue
+ elif len(imagecolor) > 0:
+ if colors is None:
+ testDye(id, imagecolor, "image=" + image0, fileName, True)
+ else:
+ testDyeChannel(id, imagecolor, "image=" + image0, True)
+ if colors not in colorsList:
+ print "error: " + fileName + ": colors value " + colors + " not found in itemcolors.xml"
+ errors = errors + 1
+
+ if floorcolor != None and len(floorcolor) > 0:
+ if colors is None:
+ testDye(id, floorcolor, "floor=" + floor0, fileName, True)
+ else:
+ testDyeChannel(id, imagecolor, "floor=" + floor0, True);
+ if colors not in colorsList:
+ print "error: " + fileName + ": colors value " + colors + " not found in itemcolors.xml"
+ errors = errors + 1
+
+ if description == "":
+ print "warn: " + fileName + ": missing description attribute on id=" + id
+ warnings = warnings + 1
+ elif description == ".":
+ print "warn: " + fileName + ": broken description attribute on id=" + id
+ warnings = warnings + 1
+
+ if missile != "":
+ testParticle(id, missile, fileName)
+
+ testSounds(id, node, "item")
+
+ try:
+ floorSprite = node.getElementsByTagName("floor")[0]
+ except:
+ floorSprite = None
+ if floorSprite != None:
+ if floor != None:
+ print "error: " + fileName + ": found attribute floor and tag floor. " + \
+ "Should be only one tag or attribute. id=" + id
+ errors = errors + 1
+ testSprites(id, floorSprite, False, colors is None, True, "", err)
+
+ fullPath = os.path.abspath(parentDir + "/" + imgDir + image)
+ if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False:
+ showFileErrorById (id, imgDir, image)
+ errors = errors + 1
+ else:
+ testImageFile(imgDir + image, fullPath, 32, "", True)
+
+ if floor != None:
+ fullPath = os.path.abspath(parentDir + "/" + imgDir + floor)
+ if not os.path.isfile(fullPath) or os.path.exists(fullPath) == False:
+ showFileErrorById (id, imgDir, floor)
+ errors = errors + 1
+ else:
+ testImageFile(imgDir + floor, fullPath, 0, "", True)
+
+ testItemReplace(id, node, "replace")
+ if drawBefore != "":
+ checkSpriteName(id, drawBefore)
+ if drawAfter != "":
+ checkSpriteName(id, drawAfter)
+
+ try:
+ attackaction = node.attributes["attack-action"].value
+ except:
+ attackaction = ""
+
+ testSprites(id, node, True, colors is None, False, attackaction, True)
+
+ if type != "usable" and type != "unusable" and type != "generic" \
+ and type != "equip-necklace" and type != "equip-1hand" \
+ and type != "equip-2hand" and type != "equip-ammo" \
+ and type != "equip-charm" and type != "equip-neck":
+ err = type != "equip-shield"
+ testSprites(id, node, True, colors is None, True, "", err)
+ elif type == "other":
+ None
+ elif type != "":
+ print "warn: " + fileName + ": unknown type '" + type + "' for id=" + id
+ warnings = warnings + 1
+
+
+def testItemReplace(id, rootNode, name):
+ global warnings, errors
+ for node in rootNode.getElementsByTagName(name):
+ if node.parentNode != rootNode:
+ continue
+ try:
+ sprite = node.attributes["sprite"].value
+ except:
+ if len(node.attributes) != 0:
+ print "error: reading replace sprite name, id=" + str(id)
+ errors = errors + 1
+ continue
+ checkSpriteName(id, sprite)
+ for itemNode in node.getElementsByTagName("item"):
+ if itemNode.parentNode != node:
+ continue
+ #TODO here need check "from" and "to" for correct item id
+
+
+def checkSpriteName(id, name):
+ global warnings, errors
+ if name != "race" and name != "type" and name != "shoes" and name != "boot" and \
+ name != "boots" and name != "bottomclothes" \
+ and name != "bottom" and name != "pants" and name != "topclothes" and \
+ name != "top" and name != "torso" and name != "body" and name != "misc1" \
+ and name != "misc2" and name != "scarf" and name != "scarfs" and \
+ name != "hair" and name != "hat" and name != "hats" and name != "wings" \
+ and name != "glove" and name != "gloves" and name != "weapon" and \
+ name != "weapons" and name != "shield" and name != "shields" and \
+ name != "amulet" and name != "amulets" and name != "ring" and name != "rings":
+ print "error: unknown sprite name " + name + ", id=" + str(id)
+ errors = errors + 1
+
+
+def testMonsters(fileName):
+ global warnings, errors
+ if not stfu:
+ print "Checking " + fileName
+ dom = minidom.parse(parentDir + "/" + fileName)
+ idset = set()
+ for node in dom.documentElement.childNodes:
+ if node.nodeName == "include":
+ try:
+ name = node.attributes["name"].value
+ if name == "":
+ errors = errors + 1
+ print "error: " + fileName + ": Empty include name";
+ testMonsters(name)
+ except:
+ errors = errors + 1
+ print "error: " + fileName + ": Broken include tag";
+ continue
+ if node.nodeName == "monster":
+ try:
+ id = node.attributes["id"].value
+ except:
+ print "error: " + fileName + ": no id for monster"
+ errors = errors + 1
+ continue
+
+ if id in idset:
+ print "error: " + fileName + ": duplicate id=" + id
+ errors = errors + 1
+ else:
+ idset.add(id)
+
+ try:
+ name = node.attributes["name"].value
+ except:
+ print "error: " + fileName + ": no name for id=" + id
+ errors = errors + 1
+ name = ""
+
+ testTargetCursor(id, node, fileName)
+ testSprites(id, node, False, True, True, "", True)
+ testSounds(id, node, "monster")
+ testParticles(id, node, "particlefx", fileName)
+
+def testTargetCursor(id, node, file):
+ try:
+ targetCursor = node.attributes["targetCursor"].value
+ if targetCursor != "small" and targetCursor != "medium" and targetCursor != "large":
+ showMsgFile(id, "unknown target cursor " + targetCursor, True)
+ except:
+ None
+
+def testParticles(id, node, nodeName, src):
+ particles = node.getElementsByTagName(nodeName)
+ for particle in particles:
+ try:
+ particlefx = particle.childNodes[0].data
+ except:
+ showMsgFile(id, "particle tag have incorrect data", True)
+
+ testParticle(id, particlefx, src)
+
+
+
+def testSounds(id, node, type):
+ global errors
+ havemiss = False
+ for sound in node.getElementsByTagName("sound"):
+ try:
+ event = sound.attributes["event"].value
+ except:
+ print "error: no sound event name in id=" + id
+ errors = errors + 1
+
+ if type == "monster":
+ if event != "hit" and event != "miss" and event != "hurt" and event != "die" \
+ and event != "move" and event != "sit" and event != "spawn":
+ print "error: incorrect sound event name " + event + " in id=" + id
+ errors = errors + 1
+ elif type == "item":
+ if event != "hit" and event != "strike" and event != "miss":
+ print "error: incorrect sound event name " + event + " in id=" + id
+ errors = errors + 1
+ if event == "strike" or event == "miss":
+ if havemiss:
+ print "error: miss and strike attributes at same time in id=" + id
+ errors = errors + 1
+ havemiss = True
+
+ testSound(sound.childNodes[0].data, sfxDir, "")
+
+def testNpcs(file):
+ global warnings, errors
+ if not stfu:
+ print "Checking " + file
+ dom = minidom.parse(parentDir + "/" + file)
+ idset = set()
+ for node in dom.documentElement.childNodes:
+ if node.nodeName == "include":
+ try:
+ name = node.attributes["name"].value
+ if name == "":
+ errors = errors + 1
+ print "error: " + file + ": Empty include name";
+ testNpcs(name)
+ except:
+ errors = errors + 1
+ print "error: " + file + ": Broken include tag";
+ continue
+ if node.nodeName != "npc":
+ continue
+
+ try:
+ id = node.attributes["id"].value
+ except:
+ print "error: " + file + ": no id for npc"
+ errors = errors + 1
+ continue
+
+ if id in idset:
+ print "error: " + file + ": duplicate npc id=" + id
+ errors = errors + 1
+ else:
+ idset.add(id)
+
+ testSprites(id, node, False, True, True, "", True)
+ testParticles(id, node, "particlefx", file)
+
+def readAttrI(node, attr, dv, msg, iserr):
+ return int(readAttr(node, attr, dv, msg, iserr))
+
+def readAttr(node, attr, dv, msg, iserr):
+ global warnings, errors
+ try:
+ return node.attributes[attr].value
+ except:
+ print msg
+ if iserr:
+ errors = errors + 1
+ else:
+ warnings = warnings + 1
+ return dv
+
+def readAttr2(node, attr, dv):
+ try:
+ return node.attributes[attr].value
+ except:
+ return dv
+
+
+def testMap(mapName, file, path):
+ global warnings, errors
+ fullPath = parentDir + "/" + path
+ dom = minidom.parse(fullPath)
+ root = dom.documentElement
+ mapWidth = readAttrI(root, "width", 0, "error: missing map width: " + file, True)
+ mapHeight = readAttrI(root, "height", 0, "error: missing map height: " + file, True)
+ mapTileWidth = readAttrI(root, "tilewidth", 0, "error: missing tile width: " + file, True)
+ mapTileHeight = readAttrI(root, "tileheight", 0, "error: missing tile height: " + file, True)
+ mapVersion = readAttr(root, "version", "1.0", "error: missing map version: " + file, True)
+
+ if mapWidth == 0 or mapHeight == 0 or mapTileWidth == 0 or mapTileHeight == 0:
+ return
+
+ mapVersion = mapVersion.replace(".", "")
+ try:
+ mapVersion = int(mapVersion)
+ except:
+ showMsgFile(file, "Invalid map version: " + str(mapVersion), False)
+
+ if mapVersion < tiledVersion:
+ showMsgFile(file, "Outdated map version: " + str(mapVersion), False)
+
+ if mapWidth < borderSize * 2 + 1:
+ if silent == False or file.find("maps/test") != 0:
+ showMsgFile(file, "map width to small: " + str(mapWidth), False)
+ if mapHeight < borderSize * 2 + 1:
+ if silent == False or file.find("maps/test") != 0:
+ showMsgFile(file, "map height to small: " + str(mapHeight), False)
+
+ if len(dom.getElementsByTagName("properties")) < 1:
+ showMsgFile(file, "missing map properties", True)
+ return
+
+ for props in dom.getElementsByTagName("properties"):
+ for prop in props.getElementsByTagName("property"):
+ try:
+ name = prop.attributes["name"].value
+ except:
+ name = ""
+ if name == "":
+ showMsgFile(file, "wrong property", True)
+ continue
+ try:
+ value = prop.attributes["value"].value
+ except:
+ value = ""
+ if value == "" and name == "name":
+ showMsgFile(file, "empty map name property", True)
+ continue
+
+ # Total minimum required width
+ if mapWidth < 60:
+ name1=file.find("maps/test")
+ name2=file.find("maps/000-1")
+ if name1 == 0 or name2 == 0:
+ pass
+ else:
+ showMsgFile(file, "total map width to small: " + str(mapWidth), False)
+
+ tilesMap = dict()
+
+ for tileset0 in dom.getElementsByTagName("tileset"):
+ tileset = tileset0
+ try:
+ firstGid = int(tileset.attributes["firstgid"].value)
+ except:
+ firstGid = 0
+
+ try:
+ source = tileset.attributes["source"].value
+ if source is not None and source != "":
+ file2 = os.path.abspath(parentDir + os.path.sep + mapsDir + source)
+ if not os.path.isfile(file2):
+ showMsgFile(file, "missing source file in tileset " + source, True)
+ except:
+ source = ""
+
+ tile = Tileset()
+ tile.firstGid = firstGid
+ tile.lastGid = 0
+
+ if source[-4:] == ".tsx":
+ relativePath = parentDir + "/" + mapsDir + source
+ try:
+ dom2 = minidom.parse(relativePath)
+ tileset = dom2.documentElement
+ idx = relativePath.rfind("/")
+ relativePath = relativePath[:idx+1]
+ relativePath2 = source
+ idx = relativePath2.rfind("/")
+ relativePath2 = relativePath2[:idx+1]
+ except:
+ showMsgFile(file, "tsx not found: " + source, True)
+ relativePath = ""
+ relativePath2 = ""
+ else:
+ relativePath = ""
+ relativePath2 = ""
+
+ name = readAttr(tileset, "name", "", "warning: missing tile name: " + file, False)
+ tileWidth = readAttrI(tileset, "tilewidth", mapTileWidth, \
+ "error: missing tile width in tileset: " + name + ", " + file, True)
+ tileHeight = readAttrI(tileset, "tileheight", mapTileHeight, \
+ "error: missing tile height in tileset: " + name + ", " + file, True)
+ if firstGid in tilesMap:
+ showMsgFile(file, "tile with firstgid " + str(firstGid) + \
+ " already exist: " + name + ", " + file, True)
+ continue
+
+ tile.width = tileWidth
+ tile.tileWidth = tileWidth
+ tile.height = tileHeight
+ tile.tileHeight = tileHeight
+ tile.name = name
+
+ images = tileset.getElementsByTagName("image")
+ if images == None or len(images) == 0:
+ showMsgFile(file, "missing image tags in tile " + name, True)
+ continue
+ elif len(images) > 1:
+ showMsgFile(file, "to many image tags in tile " + name, True)
+ continue
+
+ image = images[0]
+ source = readAttr(image, "source", None, "error: missing source in image tag in tile " \
+ + name + ": " + file, True)
+
+ if source != None:
+ if relativePath == "":
+ imagePath = os.path.abspath(parentDir + "/" + mapsDir + source)
+ else:
+ imagePath = os.path.abspath(relativePath + source)
+
+ img = splitImage(imagePath)
+ imagePath = img[0]
+ imagecolor = img[1]
+
+ tile.image = imagePath
+ tile.color = imagecolor
+
+ if not os.path.isfile(imagePath) or os.path.exists(imagePath) == False:
+ showMsgFile(file, "image file not exist: " + mapsDir + source + ", " + \
+ name, True)
+ continue
+
+ if imagecolor != "":
+ testDye("", imagecolor, source, file, True)
+
+ sz = testImageFile(file, imagePath, 0, "", True)
+ width = sz[0]
+ height = sz[1]
+
+ if width == 0 or height == 0:
+ continue
+
+ if width < tileWidth:
+ showMsgFile(file, "tile width more than image width in tile: " + \
+ name, True)
+ continue
+ if height < tileHeight:
+ showMsgFile(file, "tile height more than image height in tile: " + \
+ name, True)
+ continue
+
+ s1 = int(width / int(tileWidth)) * int(tileWidth)
+
+ if width != s1:
+ if s1 == 0:
+ s1 = int(tileWidth)
+ showMsgFile(file, "image width " + str(width) + \
+ " (need " + str(s1) + ") is not multiply to tile size " + \
+ str(tileWidth) + ". " + source + ", " + name, False)
+
+ s2 = int(height / int(tileHeight)) * int(tileHeight)
+
+ tile.lastGid = tile.firstGid + (int(width / int(tileWidth)) * int(height / int(tileHeight))) - 1
+ if height != s2:
+ if s2 == 0:
+ s2 = int(tileHeight)
+ showMsgFile(file, "image width " + str(height) + \
+ " (need " + str(s2) + ") is not multiply to tile size " + \
+ str(tileHeight) + ". " + source + ", " + name, False)
+
+ tile.source = relativePath2 + source
+ # hack to change relative back path to normal relative path
+ if len(tile.source) > 3 and tile.source[:11] == "../graphics":
+ tile.source = tile.source[3:]
+ tilesMap[tile.firstGid] = tile
+
+ if mapName not in mapToAtlas:
+ showMsgFile(file, "map dont have atlas", True)
+
+ tileset = tileset0
+
+ testTiles(mapName, file, tilesMap)
+ layers = dom.getElementsByTagName("layer")
+ objects = dom.getElementsByTagName("object")
+ if layers == None or len(layers) == 0:
+ showMsgFile(file, "map dont have layers", True)
+ return
+
+ fringe = None
+ collision = None
+ lowLayers = []
+ overLayers = []
+ beforeFringe = True
+ haveHeight = False
+
+ for layer in layers:
+ name = readAttr(layer, "name", None, "layer dont have name", True)
+ if name == None:
+ continue
+ if name.lower() == "height" or name.lower() == "heights":
+ haveHeight=True
+ obj = Layer()
+ obj.name = name
+ if name.lower() == "fringe":
+ if fringe is not None:
+ showMsgFile(file, "duplicate Fringe layer", True)
+ fringe = obj
+ beforeFringe = False
+ elif name.lower() == "collision":
+ if collision is not None:
+ showMsgFile(file, "duplicate Collision layer", True)
+ collision = obj
+ elif beforeFringe == True:
+ lowLayers.append(obj)
+ else:
+ overLayers.append(obj)
+
+ width = readAttrI(layer, "width", 0, "error: missing layer width: " + name + \
+ ", " + file, True)
+ height = readAttrI(layer, "height", 0, "error: missing layer height: " + name + \
+ ", " + file, True)
+ if width == 0 or height == 0:
+ continue
+
+ obj.width = width
+ obj.height = height
+
+ if mapWidth < width:
+ showMsgFile(file, "layer width " + str(width) + " more than map width " + \
+ str(mapWidth) + ": " + name, True)
+ if mapHeight < height:
+ showMsgFile(file, "layer height " + str(height) + " more then map height " + \
+ str(mapHeight) + ": " + name, True)
+
+ obj = testLayer(file, layer, name, width, height, obj, tilesMap)
+ testOverSizedTiles(obj, tilesMap, file)
+
+ if fringe == None:
+ showMsgFile(file, "missing fringe layer", True)
+ if collision == None:
+ showMsgFile(file, "missing collision layer", True)
+ elif mapName != "test.tmx" and mapName != "testbg.tmx":
+ ids = testCollisionLayer(file, collision, tilesMap)
+ if ids[0] != None and len(ids[0]) > 0:
+ if silent == False or file.find("maps/test") != 0:
+ showLayerErrors(file, ids[0], "empty tiles in collision border", False)
+ if ids[1] != None and len(ids[1]) > 0:
+ if silent == False or file.find("maps/test") != 0:
+ showLayerErrors(file, ids[1], "incorrect tileset index in collision layer", False)
+
+ if len(lowLayers) < 1:
+ showMsgFile(file, "missing low layers", False)
+ if len(overLayers) < 1:
+ if (silent == False or file.find("maps/test") != 0) and herc == False:
+ showMsgFile(file, "missing over layers", False)
+
+ if not haveHeight:
+ showMsgFile(file, "missing height layer", False)
+
+ if fringe != None:
+ lowLayers.append(fringe)
+ warn1 = None
+
+ if len(overLayers) > 0:
+ testData = dict()
+ warn1 = testLayerGroups(file, lowLayers, collision, None, tilesMap, False)
+ lowLayers.extend(overLayers)
+ err1 = testLayerGroups(file, lowLayers, collision, testData, tilesMap, False)
+ reportAboutTiles(file, testData)
+ else:
+ testData = dict()
+ err1 = testLayerGroups(file, lowLayers, collision, testData, tilesMap, False)
+ reportAboutTiles(file, testData)
+
+ if warn1 != None and err1 != None:
+ warn1 = warn1 - err1
+ if warn1 != None and len(warn1) > 0:
+ if silent != True:
+ showLayerErrors(file, warn1, "empty tile in lower layers", False)
+ if err1 != None and len(err1) > 0:
+ showLayerErrors(file, err1, "empty tile in all layers", True)
+
+ for objx in objects:
+ x = readAttr(objx, "x", 0, "object in invalid X position", False)
+ y = readAttr(objx, "y", 0, "object in invalid Y position", False)
+ w = readAttr2(objx, "width", 0)
+ h = readAttr2(objx, "height", 0)
+ try:
+ fs=False
+ if (float(x) != int(x)):
+ showMsgFile(file, "Invalid object X pos - must be integer", False)
+ fs=1
+ if (float(y) != int(y)):
+ showMsgFile(file, "Invalid object Y pos - must be integer", False)
+ fs=1
+ if (float(w) != int(w)):
+ showMsgFile(file, "Invalid object Width - must be integer", False)
+ fs=1
+ if (float(h) != int(h)):
+ showMsgFile(file, "Invalid object Height - must be integer", False)
+ fs=1
+ if fs:
+ id1=readAttr(objx, "id", "?", "invalid object ID", False)
+ name1=readAttr(objx, "name", "?", "invalid object name", False)
+ type1=readAttr(objx, "type", "?", "invalid object type", False)
+ showMsgFile(file, "Broken object: id %s name %s (%s,%s,%s,%s) type %s" % (id1, name1, x, y, w, h, type1), True);
+ except:
+ id1=readAttr(objx, "id", "?", "invalid object ID", False)
+ showMsgFile(file, "Broken object ID %s - x/y/h/w corrupted data detected" % id1, True)
+
+def testOverSizedTiles(layer, tiles, file):
+ global warnings, errors
+
+ oversizeErrList = []
+ ignoreErrList = []
+ ignoreTilesetList = set()
+ ignoredFiles = []
+ if "ignored" in atlasToFiles:
+ ignoredFiles = atlasToFiles["ignored"]
+ for x in range(0, layer.width):
+ for y in range(0, layer.height):
+ idx = ((y * layer.width) + x) * 4
+ val = getLDV(layer.arr, idx)
+ if val == 0:
+ continue
+
+ tile, tilesetName = findTileByGid(tiles, val)
+ if layer.name.lower() not in ("collision", "heights", "height") and tilesetName in ignoredFiles:
+ ignoreErrList.append((x, y))
+ ignoreTilesetList.add(tilesetName)
+ if layer.name.lower() == "fringe":
+ continue
+ if tile is None:
+ # now ignoring, this happend because layer parser
+ # not support includes
+ None
+ elif tile.tileWidth > 32 and x + 1 < layer.width:
+ for x2 in range(x + 1, x + 1 + int(tile.width / 32), 1):
+ idx = ((y * layer.width) + x2) * 4
+ val = getLDV(layer.arr, idx)
+ tile, _ = findTileByGid(tiles, val)
+ if val > 0:
+ oversizeErrList.append((x, y))
+ if silent != True:
+ warnings = warnings + 1
+ elif tile.tileHeight > 32 and y - 1 > 0:
+ for y2 in range(y - 1, y - 1 - int(tile.height / 32), -1):
+ idx = ((y2 * layer.width) + x) * 4
+ val = getLDV(layer.arr, idx)
+ tile, _ = findTileByGid(tiles, val)
+ if val > 0:
+ oversizeErrList.append((x, y))
+ if silent != True:
+ warnings = warnings + 1
+
+ if len(oversizeErrList) > 0 and silent != True:
+ print "error: " + file + ": Oversized tile overlapped to next tile in layer " + layer.name + \
+ ". Possible incorrect map drawing"
+ errors = errors + 1
+ errStr = ""
+ k = 0
+ for err in oversizeErrList:
+ errStr = errStr + str(err) + ", "
+ k = k + 1
+ if k > 100:
+ errStr = errStr + "..."
+ break
+ print errStr
+
+ if len(ignoreErrList) > 0:
+ errStr = ""
+ for err in ignoreTilesetList:
+ if errStr != "":
+ errStr = errStr + ", "
+ errStr = errStr + err
+ print("error: {0}: Tiles from ignored atlas used in layer {1}. Tilesets: {2}. "
+ "Possible incorrect map drawing".format(file, layer.name, errStr))
+ errors = errors + 1
+ errStr = ""
+ k = 0
+ for err in ignoreErrList:
+ errStr = errStr + str(err) + ", "
+ k = k + 1
+ if k > 100:
+ errStr = errStr + "..."
+ break
+ print errStr
+
+
+def testTiles(mapName, file, tilesMap):
+ ignoredFiles = []
+ if "ignored" in atlasToFiles:
+ ignoredFiles = atlasToFiles["ignored"]
+ for firstGid in tilesMap:
+ tile1 = tilesMap[firstGid]
+ if mapName in mapToAtlas:
+ atlasName = mapToAtlas[mapName]
+ if atlasName in atlasToFiles:
+ files = atlasToFiles[atlasName]
+ if tile1.source not in files and tile1.source not in ignoredFiles:
+ showMsgFile(file, "tileset '{0} ({1})' not present in atlas '{2}'".format(
+ tile1.name,
+ tile1.source,
+ atlasName),
+ True)
+ for gid2 in tilesMap:
+ if firstGid != gid2:
+ tile2 = tilesMap[gid2]
+ if (tile1.firstGid >= tile2.firstGid and tile1.firstGid <= tile2.lastGid) or \
+ (tile1.lastGid >= tile2.firstGid and tile1.lastGid <= tile2.lastGid):
+ showMsgFile(file, "overlaping tilesets gids \"" + tile1.name \
+ + "\" and \"" + tile2.name + "\"", True)
+
+
+def reportAboutTiles(file, data):
+ if testBadCollisions == False:
+ return
+ for k in data:
+ d = data[k]
+ if d[0] != 0 and d[2] != 0:
+ #print file + ": " + str(k) + ": " + str(d)
+ testCollisionPoints(file, k, d, 1, 3, \
+ "possible tiles should be without collision: ", \
+ "because no collision: ", False)
+ testCollisionPoints(file, k, d, 3, 1, \
+ "possible tiles should be with collision: ", \
+ "because collision: ", False)
+
+
+def testCollisionPoints(file, tileId, data, idx1, idx2, msg1, msg2, iserr):
+ #print "test: " + str(idx1) + ", " + str(idx2)
+ cnt1 = 0
+ cnt2 = 0
+ for point in data[idx1]:
+ if point[2] > 0:
+ cnt1 = cnt1 + 1
+ for point in data[idx2]:
+ if point[2] > 0:
+ cnt2 = cnt2 + 1
+
+ ln1 = len(data[idx1])
+ ln2 = len(data[idx2])
+ #print "cnt1=" + str(cnt1) + ", cnt2=" + str(cnt2) + ", ln1=" + str(ln1) + ", ln2=" + str(ln2)
+ if ln1 > 0 and ln2 > 0 and cnt2 > 0 and cnt2 < cnt1 - tileNumDiff and cnt2 < maxNumErrTiles:
+ text = msg1
+ c = 0
+ for point in data[idx2]:
+ if point[2] > 0:
+ if c > 100:
+ break
+ text = text + "(" + str(point[0]) + ", " + str(point[1]) + "), "
+ c = c + 1
+ text = text[:len(text)-2] + " " + msg2
+ c = 0
+ for point in data[idx1]:
+ if c > 100:
+ break
+ text = text + "(" + str(point[0]) + ", " + str(point[1]) + "), "
+ c = c + 1
+ showMsgFile(file, text[:len(text)-2], iserr)
+
+
+def testCollisionLayer(file, layer, tiles):
+ haveTiles = False
+ tileset = set()
+ badtiles = set()
+ arr = layer.arr
+ x1 = borderSize
+ y1 = borderSize
+ x2 = layer.width - borderSize
+ y2 = layer.height - borderSize
+ if x2 < 0:
+ x2 = 0
+ if y2 < 0:
+ y2 = 0
+
+ if arr is None :
+ return (set(), set())
+
+ for x in range(0, layer.width):
+ for y in range(0, layer.height):
+ idx = ((y * layer.width) + x) * 4
+ val = getLDV(arr, idx)
+ if val != 0:
+ haveTiles = True
+ tile, tilesetName = findTileByGid(tiles, val)
+ if tile is not None:
+ idx = val - tile.firstGid
+ if idx > 6: # 6 - max collision type
+ badtiles.add(((x, y), idx))
+ else:
+ badtiles.add(((x, y), "+{0}".format(val)))
+ if val == 0 and (x < x1 or x > x2 or y < y1 or y > y2):
+ tileset.add((x, y))
+
+ if haveTiles == False:
+ if silent == False or file.find("maps/test") != 0:
+ showMsgFile(file, "empty collision layer", False)
+ return (set(), set())
+
+ return (tileset, badtiles)
+
+
+def findTileByGid(tiles, gid):
+ for firstGid in tiles:
+ if firstGid <= gid:
+ tile = tiles[firstGid]
+ if tile.lastGid >= gid:
+ return (tile, tile.source)
+ return (None, None)
+
+
+def showLayerErrors(file, points, msg, iserr):
+ txt = ""
+ cnt = 0
+ for point in points:
+ txt = txt + " " + str(point) + ","
+ cnt = cnt + 1
+ if cnt > 100:
+ txt = txt + " ... "
+ break
+ showMsgFile(file, msg + txt[0:len(txt)-1], iserr)
+
+
+def getLDV(arr, index):
+ return arr[index] | (arr[index + 1] << 8) | (arr[index + 2] << 16) \
+ | (arr[index + 3] << 24)
+
+
+def getLDV2(arr, x, y, width, height, tilesMap):
+ ptr = ((y * width) + x) * 4
+ res = getLDV(arr, ptr)
+ yend = height - 1
+ if yend - y > 5:
+ yend = y + 5
+ for y2 in range(height - 1, y, -1):
+ x0 = x - 3
+ if x0 < 0:
+ x0 = 0
+ for x2 in range(x0, x + 1):
+ ptr = ((y2 * width) + x2) * 4
+ val = getLDV(arr, ptr)
+ tile, _ = findTileByGid(tilesMap, val)
+ if tile is not None:
+ if (tile.tileHeight > 32 or y2 == y) and (tile.tileWidth > 32 or x2 == x):
+ hg = tile.tileHeight / 32
+ wg = tile.tileWidth / 32
+ if (y2 - y < hg or y2 == y) and (x2 - x < wg or x2 == x):
+ res = val
+
+ return res
+
+
+def testLayer(file, node, name, width, height, layer, tiles):
+ datas = node.getElementsByTagName("data")
+ if datas == None or len(datas) == 0:
+ showMsgFile(file, "missing data tag in layer: " + name, True)
+ return
+ layer.arr = None
+ for data in datas:
+ try:
+ encoding = data.attributes["encoding"].value
+ except:
+ encoding = ""
+ try:
+ compression = data.attributes["compression"].value
+ except:
+ compression = ""
+ if encoding == "base64":
+# if compression != "gzip":
+# if compression != "zlib":
+# showMsgFile(file, "invalid compression " + compression + \
+# " in layer: " + name, True)
+# continue
+# else:
+# showMsgFile(file, "not supported compression by old clients " \
+# + compression + " in layer: " + name, False)
+ binData = data.childNodes[0].data.strip()
+ binData = binData.decode('base64')
+ if compression == "gzip":
+ dc = zlib.decompressobj(16 + zlib.MAX_WBITS)
+ else:
+ dc = zlib.decompressobj()
+ layerData = dc.decompress(binData)
+ arr = array.array("B")
+ arr.fromstring(layerData)
+ layer.arr = arr
+# print file
+# for item in arr:
+# print item
+ elif encoding == "csv":
+ if compression != "":
+ showMsgFile(file, "not supported compression " + compression + \
+ " for csv layer format:" + name, True)
+ binData = data.childNodes[0].data.strip()
+ f = StringIO.StringIO(binData)
+ arr = list(csv.reader(f, delimiter=',', quotechar='|'))
+ layer.arr = []
+# print file
+ for row in arr:
+ try:
+ for item in row:
+ if item != "":
+ nums = splitBytes(int(item))
+ layer.arr.append(nums[0])
+ layer.arr.append(nums[1])
+ layer.arr.append(nums[2])
+ layer.arr.append(nums[3])
+ except:
+ None
+
+ f.close()
+ arr = array.array('i', (layer.arr))
+ layer.arr = arr
+# for item in arr:
+# print item
+
+ elif encoding == "":
+ if compression != "":
+ showMsgFile(file, "not supported compression " + compression + \
+ " for xml layer format:" + name, True)
+
+ layer.arr = []
+ tiles = data.getElementsByTagName("tile")
+# print file
+ for tile in tiles:
+ try:
+ gid = int(tile.attributes["gid"].value)
+ except:
+ showMsgFile(file, "incorrect xml layer format: " + name, True)
+ return layer
+ nums = splitBytes(gid)
+ layer.arr.append(nums[0])
+ layer.arr.append(nums[1])
+ layer.arr.append(nums[2])
+ layer.arr.append(nums[3])
+
+ arr = array.array('i', (layer.arr))
+ layer.arr = arr
+# for item in arr:
+# print item
+
+
+ # here may be i should check is tiles correct or not, but i will trust to tiled
+ return layer
+
+
+def splitBytes(num):
+ i1 = int(num % 256)
+ i2 = int(((num % 65536) - i1) / 256)
+ i3 = int(((num % 16777216) - i2 - i1) / 65536)
+ i4 = int(((num % 4294967296) - i3 - i2 - i1) / 16777216)
+ return (i1, i2, i3, i4)
+
+def testLayerGroups(file, layers, collision, tileInfo, tilesMap, iserr):
+ width = 0
+ height = 0
+ errset = set()
+ for layer in layers:
+ if layer.width > width:
+ width = layer.width
+ if layer.height > height:
+ height = layer.height
+
+ for x in range(0, width):
+ for y in range(0, height):
+ good = False
+ lastTileId = 0
+ for layer in layers:
+ if layer.arr != None and x < layer.width \
+ and y < layer.height:
+ arr = layer.arr
+ ptr = ((y * layer.width) + x) * 4
+ if testBadCollisions == True:
+ val = getLDV2(arr, x, y, layer.width, layer.height, tilesMap)
+ else:
+ val = 0
+ val1 = getLDV(arr, ptr)
+ if val1 != 0:
+ good = True
+ if val == val1 and testBadCollisions == True:
+ lastTileId = val
+ if good == False:
+ errset.add((x,y))
+ elif testBadCollisions == True and collision != None and tileInfo != None:
+ if lastTileId not in tileInfo:
+ tileInfo[lastTileId] = [0, set(), 0, set()]
+ ti = tileInfo[lastTileId]
+ flg = getLDV(collision.arr, ((y * collision.width) + x) * 4)
+ cnt = countCollisionsNear(collision, x, y)
+ k = 0
+ if flg > 0:
+ if cnt[1] < cnt[0] and cnt[0] - cnt[1] > 5:
+ k = 1
+ ti[2] = ti[2] + 1
+ ti[3].add((x, y, k))
+ else:
+ if cnt[0] > cnt[1] and cnt[0] - cnt[1] > 5:
+ k = 1
+ ti[0] = ti[0] + 1
+ ti[1].add((x, y, k))
+
+ return errset
+
+
+def countCollisionsNear(layer, x, y):
+ arr = layer.arr
+ x1 = x - 1
+ y1 = y - 1
+ x2 = x + 1
+ y2 = y + 1
+ col = 0
+ nor = 0
+
+ if x1 < 0:
+ x1 = 0
+ if x2 >= layer.width:
+ x2 = layer.width - 1
+ if y1 < 0:
+ y1 = 0
+ if y2 >= layer.height:
+ y2 = layer.height - 1
+
+ for f in range(x1, x2 + 1):
+ for d in range(y1, y2 + 1):
+ if f != x or d != y:
+ val = getLDV(arr, ((d * layer.width) + f) * 4)
+ if val == 0:
+ nor = nor + 1
+ else:
+ col = col + 1
+ return (nor, col)
+
+
+def testMaps(dir):
+ global warnings, errors
+ fullPath = parentDir + "/" + dir
+ print "Checking maps"
+ if not os.path.isdir(fullPath) or not os.path.exists(fullPath):
+ print "error: maps dir not found: " + dir
+ errors = errors + 1
+ return
+
+ for file in os.listdir(fullPath):
+ if filtmaps.search(file):
+ testMap(file, mapsDir + file, dir + file)
+
+def testDirExists(path):
+ global errors
+ fullName = parentDir + "/" + path
+ if not os.path.exists(fullName):
+ print "error: path '" + path + "' not exists."
+ errors = errors + 1
+ elif not os.path.isdir(fullName):
+ print "error: path '" + path + "' is incorrect directory."
+ errors = errors + 1
+
+def testDefaultFiles():
+ global warnings
+ print "Checking default files"
+ testDirExists(iconsDir)
+ testDirExists(spritesDir)
+ testDirExists(particlesDir)
+ testDirExists(minimapsDir)
+ testDirExists(mapsDir)
+ testDirExists(sfxDir)
+ if silent != True:
+ testDirExists(musicDir)
+ testDirExists(wallpapersDir)
+
+ testSprite("0", spriteErrorFile, 0, True, "", True)
+ testParticle("0", particlesDir + levelUpEffectFile, "levelUpEffectFile")
+ testParticle("0", particlesDir + portalEffectFile, "portalEffectFile")
+ fullName = parentDir + "/" + wallpapersDir + wallpaperFile
+ if not os.path.isdir(fullName) and os.path.exists(fullName):
+ testImageFile(wallpapersDir + wallpaperFile, fullName, 0, "", False)
+
+
+def testMinimapsDir():
+ global errors, warnings
+
+ print "Checking minimaps"
+ fullPath = parentDir + "/" + minimapsDir
+ if not os.path.isdir(fullPath) or not os.path.exists(fullPath):
+ print "warn: minimaps dir not exist"
+ warnings = warnings + 1
+ return
+ for file in os.listdir(fullPath):
+ if filtimages.search(file):
+ fullName = parentDir + "/" + minimapsDir + file
+ testImageFile(minimapsDir + file, fullName, 0, "", True)
+
+
+def testImagesDir(imagesDir, sz):
+ global errors, warnings
+
+ fullPath = parentDir + "/" + imagesDir
+ if not os.path.isdir(fullPath) or not os.path.exists(fullPath):
+ return
+ for file in os.listdir(fullPath):
+ file2 = fullPath + "/" + file
+ if file[0] == ".":
+ continue
+ if not os.path.isfile(file2):
+ testImagesDir(imagesDir + file + "/", sz)
+ if filtimages.search(file):
+ fullName = parentDir + "/" + imagesDir + file
+ testImageFile(imagesDir + file, fullName, sz, "", True)
+
+
+def testSpritesDir(dir):
+ global errors, warnings, safeDye
+
+ fullPath = parentDir + "/" + spritesDir + dir
+ if not os.path.isdir(fullPath) or not os.path.exists(fullPath):
+ return
+
+ for file in os.listdir(fullPath):
+ file2 = fullPath + "/" + file
+ if file[0] == ".":
+ continue
+ if not os.path.isfile(file2):
+ testSpritesDir(dir + file + "/")
+ if filtimages.search(file):
+ fullName = parentDir + "/" + spritesDir + dir + file
+ testImageFile(spritesDir + dir, fullName, 0, spritesDir + dir + file, True)
+ elif filtxmls.search(file):
+ fullName = dir + file
+ safeDye = True
+ testSprite("0", dir + file, 0, True, "", True)
+ safeDye = False
+
+
+
+def testParticlesDir(dir):
+ global errors, warnings, safeDye
+
+ fullPath = parentDir + "/" + dir
+ if not os.path.isdir(fullPath) or not os.path.exists(fullPath):
+ return
+ for file in os.listdir(fullPath):
+ file2 = fullPath + "/" + file
+ if file[0] == ".":
+ continue
+ if not os.path.isfile(file2):
+ testParticlesDir(dir + file + "/")
+ if filtimages.search(file):
+ fullName = parentDir + "/" + dir + file
+ testImageFile(dir + file, fullName, 0, "", True)
+ elif filtxmls.search(file):
+ fullName = dir + file
+ safeDye = True
+ testParticle("0", dir + file, "")
+ safeDye = False
+
+
+def testSoundsDir(dir, sfxDir):
+ global errors, warnings
+
+ fullPath = parentDir + "/" + sfxDir + dir
+ if not os.path.isdir(fullPath) or not os.path.exists(fullPath):
+ print "warn: directory " + sfxDir + " not exist"
+ warnings = warnings + 1
+ return
+ for file in os.listdir(fullPath):
+ file2 = fullPath + "/" + file
+ if file[0] == ".":
+ continue
+ if not os.path.isfile(file2):
+ testSoundsDir(dir + file + "/", sfxDir)
+ elif filtogg.search(file):
+ testSound(dir + file, sfxDir, "")
+
+
+def testItemColors(fileName):
+ global warnings, errors, safeDye, colorLists
+ print "Checking itemcolors.xml"
+ try:
+ dom = minidom.parse(parentDir + "/" + fileName)
+ except:
+ return
+
+ for node in dom.getElementsByTagName("list"):
+ if node.parentNode != dom.documentElement:
+ continue
+
+ try:
+ name = node.attributes["name"].value
+ except:
+ print "error: colors list dont have name"
+ errors = errors + 1
+ continue
+ if name in colorsList:
+ print "error: duplicate color list: " + name
+ errors = errors + 1
+ continue
+ colorsList.add(name)
+ colors = set()
+ names = set()
+ for colorNode in node.getElementsByTagName("color"):
+ if colorNode.parentNode != node:
+ continue
+ try:
+ id = colorNode.attributes["id"].value
+ except:
+ print "error: getting id in list: " + name
+ errors = errors + 1
+ continue
+ try:
+ colorName = colorNode.attributes["name"].value
+ except:
+ print "error: getting name in list: " + name
+ errors = errors + 1
+ continue
+ try:
+ colorDye = colorNode.attributes["value"].value
+ except:
+ print "error: getting color in list: " + name
+ errors = errors + 1
+ if id in colors:
+ print "error: color with id " + str(id) + " already in list: " + name
+ errors = errors + 1
+ else:
+ colors.add(id)
+ if colorName in names:
+ print "error: color with name \"" + colorName + "\" already in list: " + name
+ errors = errors + 1
+ else:
+ names.add(colorName)
+ testDyeColors(id, colorDye, colorDye, name, True)
+
+def loadMapAtlases(fileName):
+ mapToAtlas = dict()
+ atlasToFiles = dict()
+ try:
+ root = ElementTree.parse(parentDir + "/" + fileName).getroot()
+ except:
+ showMsgFile(fileName, "load xml error. Probably file missing", True)
+ return (mapToAtlas, atlasToFiles)
+
+ for node in root.findall("map"):
+ mapName = node.attrib["name"]
+ atlasNode = node.find("atlas")
+ if atlasNode == None:
+ continue
+ atlasName = atlasNode.attrib["name"]
+ mapToAtlas[mapName] = atlasName
+ for node in root.findall("atlas"):
+ atlasName = node.attrib["name"]
+ files = []
+ for fileNode in node.findall("file"):
+ fileName = fileNode.attrib["name"]
+ files.append(fileName)
+ atlasToFiles[atlasName] = files
+ for mapName in mapToAtlas:
+ atlasName = mapToAtlas[mapName]
+ if atlasName not in atlasToFiles:
+ showMsgFile(fileName, "atlas '{0}' assigned to map not present in maps.xml".format(atlasName), True)
+
+ return (mapToAtlas, atlasToFiles)
+
+def haveXml(dir):
+ if not os.path.isdir(dir) or not os.path.exists(dir):
+ return False
+ for file in os.listdir(dir):
+ if filt.search(file):
+ return True
+ return False
+
+
+def detectClientData(dirs):
+ global parentDir
+
+ for dir in dirs:
+ if haveXml(dir):
+ print "Detected client data directory in: " + dir
+ parentDir = dir
+ return True
+
+ print "Cant detect client data directory"
+ exit(1)
+
+
+if len(sys.argv) == 2:
+ if sys.argv[1] == "all":
+ showAll = True
+ elif sys.argv[1] == "silent":
+ silent = True
+ elif sys.argv[1] == "stfu":
+ silent = True
+ stfu = True
+ elif sys.argv[1] == "herc":
+ silent = True
+ herc = True
+
+showHeader()
+print "Detecting clientdata dir"
+detectClientData([".", "..", "../../client-data", parentDir])
+print "Checking xml file syntax"
+enumDirs(parentDir)
+loadPaths()
+(mapToAtlas, atlasToFiles) = loadMapAtlases("/maps.xml")
+testDefaultFiles()
+testItemColors("/itemcolors.xml")
+testItems("/items.xml", iconsDir)
+testMonsters("/monsters.xml")
+testNpcs("/npcs.xml")
+testMaps(mapsDir)
+testMinimapsDir()
+print "Checking images dir"
+testImagesDir(wallpapersDir, 0)
+print "Checking icons dir"
+testImagesDir(iconsDir, 32)
+print "Checking sprites dir"
+testSpritesDir("")
+print "Checking particles dir"
+testParticlesDir(particlesDir)
+print "Checking sfx dir"
+testSoundsDir("", sfxDir)
+print "Checking music dir"
+if silent != True:
+ testSoundsDir("", musicDir)
+showFooter()
+if errors > 0 or warnings > 0:
+ exit(1)
diff --git a/CI/testxml/xsd/XMLSchema.xsd b/CI/testxml/xsd/XMLSchema.xsd
new file mode 100644
index 0000000..3711a93
--- /dev/null
+++ b/CI/testxml/xsd/XMLSchema.xsd
@@ -0,0 +1,2262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- XML Schema schema for XML Schemas: Part 1: Structures -->
+<!-- Note this schema is NOT the normative structures schema. -->
+<!-- The prose copy in the structures REC is the normative -->
+<!-- version (which shouldn't differ from this one except for -->
+<!-- this comment and entity expansions, but just in case -->
+<!DOCTYPE xs:schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "XMLSchema.dtd" [
+<!-- provide ID type information even for parsers which only read the
+ internal subset --><!ATTLIST xs:schema id ID #IMPLIED>
+<!ATTLIST xs:complexType id ID #IMPLIED>
+<!ATTLIST xs:complexContent id ID #IMPLIED>
+<!ATTLIST xs:simpleContent id ID #IMPLIED>
+<!ATTLIST xs:extension id ID #IMPLIED>
+<!ATTLIST xs:element id ID #IMPLIED>
+<!ATTLIST xs:group id ID #IMPLIED>
+<!ATTLIST xs:all id ID #IMPLIED>
+<!ATTLIST xs:choice id ID #IMPLIED>
+<!ATTLIST xs:sequence id ID #IMPLIED>
+<!ATTLIST xs:any id ID #IMPLIED>
+<!ATTLIST xs:anyAttribute id ID #IMPLIED>
+<!ATTLIST xs:attribute id ID #IMPLIED>
+<!ATTLIST xs:attributeGroup id ID #IMPLIED>
+<!ATTLIST xs:unique id ID #IMPLIED>
+<!ATTLIST xs:key id ID #IMPLIED>
+<!ATTLIST xs:keyref id ID #IMPLIED>
+<!ATTLIST xs:selector id ID #IMPLIED>
+<!ATTLIST xs:field id ID #IMPLIED>
+<!ATTLIST xs:include id ID #IMPLIED>
+<!ATTLIST xs:import id ID #IMPLIED>
+<!ATTLIST xs:redefine id ID #IMPLIED>
+<!ATTLIST xs:notation id ID #IMPLIED>
+<!--
+ keep this schema XML1.0 DTD valid
+ --><!ENTITY % schemaAttrs "xmlns:hfp CDATA #IMPLIED">
+<!ELEMENT hfp:hasFacet EMPTY>
+<!ATTLIST hfp:hasFacet name NMTOKEN #REQUIRED>
+<!ELEMENT hfp:hasProperty EMPTY>
+<!ATTLIST hfp:hasProperty name NMTOKEN #REQUIRED>
+<!ATTLIST hfp:hasProperty value CDATA #REQUIRED>
+<!--
+ Make sure that processors that do not read the external
+ subset will know about the various IDs we declare
+ --><!ATTLIST xs:simpleType id ID #IMPLIED>
+<!ATTLIST xs:maxExclusive id ID #IMPLIED>
+<!ATTLIST xs:minExclusive id ID #IMPLIED>
+<!ATTLIST xs:maxInclusive id ID #IMPLIED>
+<!ATTLIST xs:minInclusive id ID #IMPLIED>
+<!ATTLIST xs:totalDigits id ID #IMPLIED>
+<!ATTLIST xs:fractionDigits id ID #IMPLIED>
+<!ATTLIST xs:length id ID #IMPLIED>
+<!ATTLIST xs:minLength id ID #IMPLIED>
+<!ATTLIST xs:maxLength id ID #IMPLIED>
+<!ATTLIST xs:enumeration id ID #IMPLIED>
+<!ATTLIST xs:pattern id ID #IMPLIED>
+<!ATTLIST xs:appinfo id ID #IMPLIED>
+<!ATTLIST xs:documentation id ID #IMPLIED>
+<!ATTLIST xs:list id ID #IMPLIED>
+<!ATTLIST xs:union id ID #IMPLIED>
+]>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty" targetNamespace="http://www.w3.org/2001/XMLSchema" blockDefault="#all" elementFormDefault="qualified" version="1.0" xml:lang="EN">
+ <xs:annotation>
+ <xs:documentation>
+ Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp
+ Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp
+ </xs:documentation>
+ </xs:annotation>
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/2004/PER-xmlschema-1-20040318/structures.html">
+ The schema corresponding to this document is normative,
+ with respect to the syntactic constraints it expresses in the
+ XML Schema language. The documentation (within &lt;documentation&gt; elements)
+ below, is not normative, but rather highlights important aspects of
+ the W3C Recommendation of which this is a part</xs:documentation>
+ </xs:annotation>
+ <xs:annotation>
+ <xs:documentation>
+ The simpleType element and all of its members are defined
+ towards the end of this schema document</xs:documentation>
+ </xs:annotation>
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd">
+ <xs:annotation>
+ <xs:documentation>
+ Get access to the xml: attribute groups for xml:lang
+ as declared on 'schema' and 'documentation' below
+ </xs:documentation>
+ </xs:annotation>
+ </xs:import>
+ <xs:complexType name="openAttrs">
+ <xs:annotation>
+ <xs:documentation>
+ This type is extended by almost all schema types
+ to allow attributes from other namespaces to be
+ added to user schemas.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:restriction base="xs:anyType">
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="annotated">
+ <xs:annotation>
+ <xs:documentation>
+ This type is extended by all types which allow annotation
+ other than &lt;schema&gt; itself
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="xs:openAttrs">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:group name="schemaTop">
+ <xs:annotation>
+ <xs:documentation>
+ This group is for the
+ elements which occur freely at the top level of schemas.
+ All of their types are based on the "annotated" type by extension.</xs:documentation>
+ </xs:annotation>
+ <xs:choice>
+ <xs:group ref="xs:redefinable"/>
+ <xs:element ref="xs:element"/>
+ <xs:element ref="xs:attribute"/>
+ <xs:element ref="xs:notation"/>
+ </xs:choice>
+ </xs:group>
+ <xs:group name="redefinable">
+ <xs:annotation>
+ <xs:documentation>
+ This group is for the
+ elements which can self-redefine (see &lt;redefine&gt; below).</xs:documentation>
+ </xs:annotation>
+ <xs:choice>
+ <xs:element ref="xs:simpleType"/>
+ <xs:element ref="xs:complexType"/>
+ <xs:element ref="xs:group"/>
+ <xs:element ref="xs:attributeGroup"/>
+ </xs:choice>
+ </xs:group>
+ <xs:simpleType name="formChoice">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="qualified"/>
+ <xs:enumeration value="unqualified"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="reducedDerivationControl">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:derivationControl">
+ <xs:enumeration value="extension"/>
+ <xs:enumeration value="restriction"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="derivationSet">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ <xs:documentation>
+ #all or (possibly empty) subset of {extension, restriction}</xs:documentation>
+ </xs:annotation>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="#all"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:list itemType="xs:reducedDerivationControl"/>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:simpleType name="typeDerivationControl">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:derivationControl">
+ <xs:enumeration value="extension"/>
+ <xs:enumeration value="restriction"/>
+ <xs:enumeration value="list"/>
+ <xs:enumeration value="union"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="fullDerivationSet">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ <xs:documentation>
+ #all or (possibly empty) subset of {extension, restriction, list, union}</xs:documentation>
+ </xs:annotation>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="#all"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:list itemType="xs:typeDerivationControl"/>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:element name="schema" id="schema">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-schema"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:openAttrs">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="xs:include"/>
+ <xs:element ref="xs:import"/>
+ <xs:element ref="xs:redefine"/>
+ <xs:element ref="xs:annotation"/>
+ </xs:choice>
+ <xs:sequence minOccurs="0" maxOccurs="unbounded">
+ <xs:group ref="xs:schemaTop"/>
+ <xs:element ref="xs:annotation" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:sequence>
+ <xs:attribute name="targetNamespace" type="xs:anyURI"/>
+ <xs:attribute name="version" type="xs:token"/>
+ <xs:attribute name="finalDefault" type="xs:fullDerivationSet" use="optional" default=""/>
+ <xs:attribute name="blockDefault" type="xs:blockSet" use="optional" default=""/>
+ <xs:attribute name="attributeFormDefault" type="xs:formChoice" use="optional" default="unqualified"/>
+ <xs:attribute name="elementFormDefault" type="xs:formChoice" use="optional" default="unqualified"/>
+ <xs:attribute name="id" type="xs:ID"/>
+ <xs:attribute ref="xml:lang"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:key name="element">
+ <xs:selector xpath="xs:element"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:key name="attribute">
+ <xs:selector xpath="xs:attribute"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:key name="type">
+ <xs:selector xpath="xs:complexType|xs:simpleType"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:key name="group">
+ <xs:selector xpath="xs:group"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:key name="attributeGroup">
+ <xs:selector xpath="xs:attributeGroup"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:key name="notation">
+ <xs:selector xpath="xs:notation"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:key name="identityConstraint">
+ <xs:selector xpath=".//xs:key|.//xs:unique|.//xs:keyref"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ </xs:element>
+ <xs:simpleType name="allNNI">
+ <xs:annotation>
+ <xs:documentation>
+ for maxOccurs</xs:documentation>
+ </xs:annotation>
+ <xs:union memberTypes="xs:nonNegativeInteger">
+ <xs:simpleType>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="unbounded"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:attributeGroup name="occurs">
+ <xs:annotation>
+ <xs:documentation>
+ for all particles</xs:documentation>
+ </xs:annotation>
+ <xs:attribute name="minOccurs" type="xs:nonNegativeInteger" use="optional" default="1"/>
+ <xs:attribute name="maxOccurs" type="xs:allNNI" use="optional" default="1"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="defRef">
+ <xs:annotation>
+ <xs:documentation>
+ for element, group and attributeGroup,
+ which both define and reference</xs:documentation>
+ </xs:annotation>
+ <xs:attribute name="name" type="xs:NCName"/>
+ <xs:attribute name="ref" type="xs:QName"/>
+ </xs:attributeGroup>
+ <xs:group name="typeDefParticle">
+ <xs:annotation>
+ <xs:documentation>
+ 'complexType' uses this</xs:documentation>
+ </xs:annotation>
+ <xs:choice>
+ <xs:element name="group" type="xs:groupRef"/>
+ <xs:element ref="xs:all"/>
+ <xs:element ref="xs:choice"/>
+ <xs:element ref="xs:sequence"/>
+ </xs:choice>
+ </xs:group>
+ <xs:group name="nestedParticle">
+ <xs:choice>
+ <xs:element name="element" type="xs:localElement"/>
+ <xs:element name="group" type="xs:groupRef"/>
+ <xs:element ref="xs:choice"/>
+ <xs:element ref="xs:sequence"/>
+ <xs:element ref="xs:any"/>
+ </xs:choice>
+ </xs:group>
+ <xs:group name="particle">
+ <xs:choice>
+ <xs:element name="element" type="xs:localElement"/>
+ <xs:element name="group" type="xs:groupRef"/>
+ <xs:element ref="xs:all"/>
+ <xs:element ref="xs:choice"/>
+ <xs:element ref="xs:sequence"/>
+ <xs:element ref="xs:any"/>
+ </xs:choice>
+ </xs:group>
+ <xs:complexType name="attribute">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:sequence>
+ <xs:element name="simpleType" minOccurs="0" type="xs:localSimpleType"/>
+ </xs:sequence>
+ <xs:attributeGroup ref="xs:defRef"/>
+ <xs:attribute name="type" type="xs:QName"/>
+ <xs:attribute name="use" use="optional" default="optional">
+ <xs:simpleType>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="prohibited"/>
+ <xs:enumeration value="optional"/>
+ <xs:enumeration value="required"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="default" type="xs:string"/>
+ <xs:attribute name="fixed" type="xs:string"/>
+ <xs:attribute name="form" type="xs:formChoice"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="topLevelAttribute">
+ <xs:complexContent>
+ <xs:restriction base="xs:attribute">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:element name="simpleType" minOccurs="0" type="xs:localSimpleType"/>
+ </xs:sequence>
+ <xs:attribute name="ref" use="prohibited"/>
+ <xs:attribute name="form" use="prohibited"/>
+ <xs:attribute name="use" use="prohibited"/>
+ <xs:attribute name="name" use="required" type="xs:NCName"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:group name="attrDecls">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="attribute" type="xs:attribute"/>
+ <xs:element name="attributeGroup" type="xs:attributeGroupRef"/>
+ </xs:choice>
+ <xs:element ref="xs:anyAttribute" minOccurs="0"/>
+ </xs:sequence>
+ </xs:group>
+ <xs:element name="anyAttribute" type="xs:wildcard" id="anyAttribute">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-anyAttribute"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:group name="complexTypeModel">
+ <xs:choice>
+ <xs:element ref="xs:simpleContent"/>
+ <xs:element ref="xs:complexContent"/>
+ <xs:sequence>
+ <xs:annotation>
+ <xs:documentation>
+ This branch is short for
+ &lt;complexContent&gt;
+ &lt;restriction base="xs:anyType"&gt;
+ ...
+ &lt;/restriction&gt;
+ &lt;/complexContent&gt;</xs:documentation>
+ </xs:annotation>
+ <xs:group ref="xs:typeDefParticle" minOccurs="0"/>
+ <xs:group ref="xs:attrDecls"/>
+ </xs:sequence>
+ </xs:choice>
+ </xs:group>
+ <xs:complexType name="complexType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:group ref="xs:complexTypeModel"/>
+ <xs:attribute name="name" type="xs:NCName">
+ <xs:annotation>
+ <xs:documentation>
+ Will be restricted to required or forbidden</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="mixed" type="xs:boolean" use="optional" default="false">
+ <xs:annotation>
+ <xs:documentation>
+ Not allowed if simpleContent child is chosen.
+ May be overriden by setting on complexContent child.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="abstract" type="xs:boolean" use="optional" default="false"/>
+ <xs:attribute name="final" type="xs:derivationSet"/>
+ <xs:attribute name="block" type="xs:derivationSet"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="topLevelComplexType">
+ <xs:complexContent>
+ <xs:restriction base="xs:complexType">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:group ref="xs:complexTypeModel"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="localComplexType">
+ <xs:complexContent>
+ <xs:restriction base="xs:complexType">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:group ref="xs:complexTypeModel"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="prohibited"/>
+ <xs:attribute name="abstract" use="prohibited"/>
+ <xs:attribute name="final" use="prohibited"/>
+ <xs:attribute name="block" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="restrictionType">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:sequence>
+ <xs:choice minOccurs="0">
+ <xs:group ref="xs:typeDefParticle"/>
+ <xs:group ref="xs:simpleRestrictionModel"/>
+ </xs:choice>
+ <xs:group ref="xs:attrDecls"/>
+ </xs:sequence>
+ <xs:attribute name="base" type="xs:QName" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="complexRestrictionType">
+ <xs:complexContent>
+ <xs:restriction base="xs:restrictionType">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:choice minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>This choice is added simply to
+ make this a valid restriction per the REC</xs:documentation>
+ </xs:annotation>
+ <xs:group ref="xs:typeDefParticle"/>
+ </xs:choice>
+ <xs:group ref="xs:attrDecls"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="extensionType">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:sequence>
+ <xs:group ref="xs:typeDefParticle" minOccurs="0"/>
+ <xs:group ref="xs:attrDecls"/>
+ </xs:sequence>
+ <xs:attribute name="base" type="xs:QName" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="complexContent" id="complexContent">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-complexContent"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:choice>
+ <xs:element name="restriction" type="xs:complexRestrictionType"/>
+ <xs:element name="extension" type="xs:extensionType"/>
+ </xs:choice>
+ <xs:attribute name="mixed" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>
+ Overrides any setting on complexType parent.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="simpleRestrictionType">
+ <xs:complexContent>
+ <xs:restriction base="xs:restrictionType">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:choice minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>This choice is added simply to
+ make this a valid restriction per the REC</xs:documentation>
+ </xs:annotation>
+ <xs:group ref="xs:simpleRestrictionModel"/>
+ </xs:choice>
+ <xs:group ref="xs:attrDecls"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="simpleExtensionType">
+ <xs:complexContent>
+ <xs:restriction base="xs:extensionType">
+ <xs:sequence>
+ <xs:annotation>
+ <xs:documentation>
+ No typeDefParticle group reference</xs:documentation>
+ </xs:annotation>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:group ref="xs:attrDecls"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="simpleContent" id="simpleContent">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-simpleContent"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:choice>
+ <xs:element name="restriction" type="xs:simpleRestrictionType"/>
+ <xs:element name="extension" type="xs:simpleExtensionType"/>
+ </xs:choice>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="complexType" type="xs:topLevelComplexType" id="complexType">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-complexType"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:simpleType name="blockSet">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ <xs:documentation>
+ #all or (possibly empty) subset of {substitution, extension,
+ restriction}</xs:documentation>
+ </xs:annotation>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="#all"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:list>
+ <xs:simpleType>
+ <xs:restriction base="xs:derivationControl">
+ <xs:enumeration value="extension"/>
+ <xs:enumeration value="restriction"/>
+ <xs:enumeration value="substitution"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:list>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:complexType name="element" abstract="true">
+ <xs:annotation>
+ <xs:documentation>
+ The element element can be used either
+ at the top level to define an element-type binding globally,
+ or within a content model to either reference a globally-defined
+ element or type or declare an element-type binding locally.
+ The ref form is not allowed at the top level.</xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:sequence>
+ <xs:choice minOccurs="0">
+ <xs:element name="simpleType" type="xs:localSimpleType"/>
+ <xs:element name="complexType" type="xs:localComplexType"/>
+ </xs:choice>
+ <xs:group ref="xs:identityConstraint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attributeGroup ref="xs:defRef"/>
+ <xs:attribute name="type" type="xs:QName"/>
+ <xs:attribute name="substitutionGroup" type="xs:QName"/>
+ <xs:attributeGroup ref="xs:occurs"/>
+ <xs:attribute name="default" type="xs:string"/>
+ <xs:attribute name="fixed" type="xs:string"/>
+ <xs:attribute name="nillable" type="xs:boolean" use="optional" default="false"/>
+ <xs:attribute name="abstract" type="xs:boolean" use="optional" default="false"/>
+ <xs:attribute name="final" type="xs:derivationSet"/>
+ <xs:attribute name="block" type="xs:blockSet"/>
+ <xs:attribute name="form" type="xs:formChoice"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="topLevelElement">
+ <xs:complexContent>
+ <xs:restriction base="xs:element">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:choice minOccurs="0">
+ <xs:element name="simpleType" type="xs:localSimpleType"/>
+ <xs:element name="complexType" type="xs:localComplexType"/>
+ </xs:choice>
+ <xs:group ref="xs:identityConstraint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="ref" use="prohibited"/>
+ <xs:attribute name="form" use="prohibited"/>
+ <xs:attribute name="minOccurs" use="prohibited"/>
+ <xs:attribute name="maxOccurs" use="prohibited"/>
+ <xs:attribute name="name" use="required" type="xs:NCName"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="localElement">
+ <xs:complexContent>
+ <xs:restriction base="xs:element">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:choice minOccurs="0">
+ <xs:element name="simpleType" type="xs:localSimpleType"/>
+ <xs:element name="complexType" type="xs:localComplexType"/>
+ </xs:choice>
+ <xs:group ref="xs:identityConstraint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="substitutionGroup" use="prohibited"/>
+ <xs:attribute name="final" use="prohibited"/>
+ <xs:attribute name="abstract" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="element" type="xs:topLevelElement" id="element">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-element"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:complexType name="group" abstract="true">
+ <xs:annotation>
+ <xs:documentation>
+ group type for explicit groups, named top-level groups and
+ group references</xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:group ref="xs:particle" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attributeGroup ref="xs:defRef"/>
+ <xs:attributeGroup ref="xs:occurs"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="realGroup">
+ <xs:complexContent>
+ <xs:restriction base="xs:group">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:choice minOccurs="0" maxOccurs="1">
+ <xs:element ref="xs:all"/>
+ <xs:element ref="xs:choice"/>
+ <xs:element ref="xs:sequence"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="namedGroup">
+ <xs:complexContent>
+ <xs:restriction base="xs:realGroup">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:choice minOccurs="1" maxOccurs="1">
+ <xs:element name="all">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="xs:all">
+ <xs:group ref="xs:allModel"/>
+ <xs:attribute name="minOccurs" use="prohibited"/>
+ <xs:attribute name="maxOccurs" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="choice" type="xs:simpleExplicitGroup"/>
+ <xs:element name="sequence" type="xs:simpleExplicitGroup"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:NCName"/>
+ <xs:attribute name="ref" use="prohibited"/>
+ <xs:attribute name="minOccurs" use="prohibited"/>
+ <xs:attribute name="maxOccurs" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="groupRef">
+ <xs:complexContent>
+ <xs:restriction base="xs:realGroup">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="ref" use="required" type="xs:QName"/>
+ <xs:attribute name="name" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="explicitGroup">
+ <xs:annotation>
+ <xs:documentation>
+ group type for the three kinds of group</xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:restriction base="xs:group">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:group ref="xs:nestedParticle" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="prohibited"/>
+ <xs:attribute name="ref" type="xs:QName" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="simpleExplicitGroup">
+ <xs:complexContent>
+ <xs:restriction base="xs:explicitGroup">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:group ref="xs:nestedParticle" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="minOccurs" use="prohibited"/>
+ <xs:attribute name="maxOccurs" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:group name="allModel">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>This choice with min/max is here to
+ avoid a pblm with the Elt:All/Choice/Seq
+ Particle derivation constraint</xs:documentation>
+ </xs:annotation>
+ <xs:element name="element" type="xs:narrowMaxMin"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:group>
+ <xs:complexType name="narrowMaxMin">
+ <xs:annotation>
+ <xs:documentation>restricted max/min</xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:restriction base="xs:localElement">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:choice minOccurs="0">
+ <xs:element name="simpleType" type="xs:localSimpleType"/>
+ <xs:element name="complexType" type="xs:localComplexType"/>
+ </xs:choice>
+ <xs:group ref="xs:identityConstraint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="minOccurs" use="optional" default="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:enumeration value="0"/>
+ <xs:enumeration value="1"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="maxOccurs" use="optional" default="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:allNNI">
+ <xs:enumeration value="0"/>
+ <xs:enumeration value="1"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="all">
+ <xs:annotation>
+ <xs:documentation>
+ Only elements allowed inside</xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:restriction base="xs:explicitGroup">
+ <xs:group ref="xs:allModel"/>
+ <xs:attribute name="minOccurs" use="optional" default="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:enumeration value="0"/>
+ <xs:enumeration value="1"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="maxOccurs" use="optional" default="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:allNNI">
+ <xs:enumeration value="1"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="all" id="all" type="xs:all">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-all"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="choice" type="xs:explicitGroup" id="choice">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-choice"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sequence" type="xs:explicitGroup" id="sequence">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-sequence"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group" type="xs:namedGroup" id="group">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-group"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:complexType name="wildcard">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:attribute name="namespace" type="xs:namespaceList" use="optional" default="##any"/>
+ <xs:attribute name="processContents" use="optional" default="strict">
+ <xs:simpleType>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="skip"/>
+ <xs:enumeration value="lax"/>
+ <xs:enumeration value="strict"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="any" id="any">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-any"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:wildcard">
+ <xs:attributeGroup ref="xs:occurs"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:annotation>
+ <xs:documentation>
+ simple type for the value of the 'namespace' attr of
+ 'any' and 'anyAttribute'</xs:documentation>
+ </xs:annotation>
+ <xs:annotation>
+ <xs:documentation>
+ Value is
+ ##any - - any non-conflicting WFXML/attribute at all
+
+ ##other - - any non-conflicting WFXML/attribute from
+ namespace other than targetNS
+
+ ##local - - any unqualified non-conflicting WFXML/attribute
+
+ one or - - any non-conflicting WFXML/attribute from
+ more URI the listed namespaces
+ references
+ (space separated)
+
+ ##targetNamespace or ##local may appear in the above list, to
+ refer to the targetNamespace of the enclosing
+ schema or an absent targetNamespace respectively</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType name="namespaceList">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ </xs:annotation>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="##any"/>
+ <xs:enumeration value="##other"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:list>
+ <xs:simpleType>
+ <xs:union memberTypes="xs:anyURI">
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="##targetNamespace"/>
+ <xs:enumeration value="##local"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:list>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:element name="attribute" type="xs:topLevelAttribute" id="attribute">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-attribute"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:complexType name="attributeGroup" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:group ref="xs:attrDecls"/>
+ <xs:attributeGroup ref="xs:defRef"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="namedAttributeGroup">
+ <xs:complexContent>
+ <xs:restriction base="xs:attributeGroup">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:group ref="xs:attrDecls"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:NCName"/>
+ <xs:attribute name="ref" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="attributeGroupRef">
+ <xs:complexContent>
+ <xs:restriction base="xs:attributeGroup">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="ref" use="required" type="xs:QName"/>
+ <xs:attribute name="name" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="attributeGroup" type="xs:namedAttributeGroup" id="attributeGroup">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-attributeGroup"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="include" id="include">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-include"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:attribute name="schemaLocation" type="xs:anyURI" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="redefine" id="redefine">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-redefine"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:openAttrs">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="xs:annotation"/>
+ <xs:group ref="xs:redefinable"/>
+ </xs:choice>
+ <xs:attribute name="schemaLocation" type="xs:anyURI" use="required"/>
+ <xs:attribute name="id" type="xs:ID"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="import" id="import">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-import"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:attribute name="namespace" type="xs:anyURI"/>
+ <xs:attribute name="schemaLocation" type="xs:anyURI"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="selector" id="selector">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-selector"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:attribute name="xpath" use="required">
+ <xs:simpleType>
+ <xs:annotation>
+ <xs:documentation>A subset of XPath expressions for use
+in selectors</xs:documentation>
+ <xs:documentation>A utility type, not for public
+use</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:token">
+ <xs:annotation>
+ <xs:documentation>The following pattern is intended to allow XPath
+ expressions per the following EBNF:
+ Selector ::= Path ( '|' Path )*
+ Path ::= ('.//')? Step ( '/' Step )*
+ Step ::= '.' | NameTest
+ NameTest ::= QName | '*' | NCName ':' '*'
+ child:: is also allowed
+ </xs:documentation>
+ </xs:annotation>
+ <xs:pattern value="(\.//)?(((child::)?((\i\c*:)?(\i\c*|\*)))|\.)(/(((child::)?((\i\c*:)?(\i\c*|\*)))|\.))*(\|(\.//)?(((child::)?((\i\c*:)?(\i\c*|\*)))|\.)(/(((child::)?((\i\c*:)?(\i\c*|\*)))|\.))*)*">
+ </xs:pattern>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="field" id="field">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-field"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:attribute name="xpath" use="required">
+ <xs:simpleType>
+ <xs:annotation>
+ <xs:documentation>A subset of XPath expressions for use
+in fields</xs:documentation>
+ <xs:documentation>A utility type, not for public
+use</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:token">
+ <xs:annotation>
+ <xs:documentation>The following pattern is intended to allow XPath
+ expressions per the same EBNF as for selector,
+ with the following change:
+ Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
+ </xs:documentation>
+ </xs:annotation>
+ <xs:pattern value="(\.//)?((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)/)*((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)|((attribute::|@)((\i\c*:)?(\i\c*|\*))))(\|(\.//)?((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)/)*((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)|((attribute::|@)((\i\c*:)?(\i\c*|\*)))))*">
+ </xs:pattern>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="keybase">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:sequence>
+ <xs:element ref="xs:selector"/>
+ <xs:element ref="xs:field" minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:group name="identityConstraint">
+ <xs:annotation>
+ <xs:documentation>The three kinds of identity constraints, all with
+ type of or derived from 'keybase'.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:choice>
+ <xs:element ref="xs:unique"/>
+ <xs:element ref="xs:key"/>
+ <xs:element ref="xs:keyref"/>
+ </xs:choice>
+ </xs:group>
+ <xs:element name="unique" type="xs:keybase" id="unique">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-unique"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="key" type="xs:keybase" id="key">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-key"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="keyref" id="keyref">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-keyref"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:keybase">
+ <xs:attribute name="refer" type="xs:QName" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="notation" id="notation">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-notation"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ <xs:attribute name="public" type="xs:public"/>
+ <xs:attribute name="system" type="xs:anyURI"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:simpleType name="public">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ <xs:documentation>
+ A public identifier, per ISO 8879</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:token"/>
+ </xs:simpleType>
+ <xs:element name="appinfo" id="appinfo">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-appinfo"/>
+ </xs:annotation>
+ <xs:complexType mixed="true">
+ <xs:sequence minOccurs="0" maxOccurs="unbounded">
+ <xs:any processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="source" type="xs:anyURI"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="documentation" id="documentation">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-documentation"/>
+ </xs:annotation>
+ <xs:complexType mixed="true">
+ <xs:sequence minOccurs="0" maxOccurs="unbounded">
+ <xs:any processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="source" type="xs:anyURI"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="annotation" id="annotation">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-1/#element-annotation"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xs:openAttrs">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="xs:appinfo"/>
+ <xs:element ref="xs:documentation"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:ID"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:annotation>
+ <xs:documentation>
+ notations for use within XML Schema schemas</xs:documentation>
+ </xs:annotation>
+ <xs:notation name="XMLSchemaStructures" public="structures" system="http://www.w3.org/2000/08/XMLSchema.xsd"/>
+ <xs:notation name="XML" public="REC-xml-19980210" system="http://www.w3.org/TR/1998/REC-xml-19980210"/>
+ <xs:complexType name="anyType" mixed="true">
+ <xs:annotation>
+ <xs:documentation>
+ Not the real urType, but as close an approximation as we can
+ get in the XML representation</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute processContents="lax"/>
+ </xs:complexType>
+ <xs:annotation>
+ <xs:documentation>
+ First the built-in primitive datatypes. These definitions are for
+ information only, the real built-in definitions are magic.
+ </xs:documentation>
+ <xs:documentation>
+ For each built-in datatype in this schema (both primitive and
+ derived) can be uniquely addressed via a URI constructed
+ as follows:
+ 1) the base URI is the URI of the XML Schema namespace
+ 2) the fragment identifier is the name of the datatype
+
+ For example, to address the int datatype, the URI is:
+
+ http://www.w3.org/2001/XMLSchema#int
+
+ Additionally, each facet definition element can be uniquely
+ addressed via a URI constructed as follows:
+ 1) the base URI is the URI of the XML Schema namespace
+ 2) the fragment identifier is the name of the facet
+
+ For example, to address the maxInclusive facet, the URI is:
+
+ http://www.w3.org/2001/XMLSchema#maxInclusive
+
+ Additionally, each facet usage in a built-in datatype definition
+ can be uniquely addressed via a URI constructed as follows:
+ 1) the base URI is the URI of the XML Schema namespace
+ 2) the fragment identifier is the name of the datatype, followed
+ by a period (".") followed by the name of the facet
+
+ For example, to address the usage of the maxInclusive facet in
+ the definition of int, the URI is:
+
+ http://www.w3.org/2001/XMLSchema#int.maxInclusive
+
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType name="string" id="string">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#string"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="preserve" id="string.preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="boolean" id="boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="finite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#boolean"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="boolean.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="float" id="float">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="total"/>
+ <hfp:hasProperty name="bounded" value="true"/>
+ <hfp:hasProperty name="cardinality" value="finite"/>
+ <hfp:hasProperty name="numeric" value="true"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#float"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="float.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="double" id="double">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="total"/>
+ <hfp:hasProperty name="bounded" value="true"/>
+ <hfp:hasProperty name="cardinality" value="finite"/>
+ <hfp:hasProperty name="numeric" value="true"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#double"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="double.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="decimal" id="decimal">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="totalDigits"/>
+ <hfp:hasFacet name="fractionDigits"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="total"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="true"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#decimal"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="decimal.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="duration" id="duration">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#duration"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="duration.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="dateTime" id="dateTime">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#dateTime"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="dateTime.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="time" id="time">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#time"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="time.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="date" id="date">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#date"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="date.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="gYearMonth" id="gYearMonth">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#gYearMonth"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="gYearMonth.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="gYear" id="gYear">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#gYear"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="gYear.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="gMonthDay" id="gMonthDay">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#gMonthDay"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="gMonthDay.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="gDay" id="gDay">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#gDay"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="gDay.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="gMonth" id="gMonth">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="maxInclusive"/>
+ <hfp:hasFacet name="maxExclusive"/>
+ <hfp:hasFacet name="minInclusive"/>
+ <hfp:hasFacet name="minExclusive"/>
+ <hfp:hasProperty name="ordered" value="partial"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#gMonth"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="gMonth.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="hexBinary" id="hexBinary">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#binary"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="hexBinary.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="base64Binary" id="base64Binary">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#base64Binary"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="base64Binary.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="anyURI" id="anyURI">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#anyURI"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="anyURI.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="QName" id="QName">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#QName"/>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="QName.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="NOTATION" id="NOTATION">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#NOTATION"/>
+ <xs:documentation>
+ NOTATION cannot be used directly in a schema; rather a type
+ must be derived from it by specifying at least one enumeration
+ facet whose value is the name of a NOTATION declared in the
+ schema.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:anySimpleType">
+ <xs:whiteSpace value="collapse" fixed="true" id="NOTATION.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:annotation>
+ <xs:documentation>
+ Now the derived primitive types
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType name="normalizedString" id="normalizedString">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#normalizedString"/>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:whiteSpace value="replace" id="normalizedString.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="token" id="token">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#token"/>
+ </xs:annotation>
+ <xs:restriction base="xs:normalizedString">
+ <xs:whiteSpace value="collapse" id="token.whiteSpace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="language" id="language">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#language"/>
+ </xs:annotation>
+ <xs:restriction base="xs:token">
+ <xs:pattern value="[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*" id="language.pattern">
+ <xs:annotation>
+ <xs:documentation source="http://www.ietf.org/rfc/rfc3066.txt">
+ pattern specifies the content of section 2.12 of XML 1.0e2
+ and RFC 3066 (Revised version of RFC 1766).
+ </xs:documentation>
+ </xs:annotation>
+ </xs:pattern>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="IDREFS" id="IDREFS">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#IDREFS"/>
+ </xs:annotation>
+ <xs:restriction>
+ <xs:simpleType>
+ <xs:list itemType="xs:IDREF"/>
+ </xs:simpleType>
+ <xs:minLength value="1" id="IDREFS.minLength"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ENTITIES" id="ENTITIES">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#ENTITIES"/>
+ </xs:annotation>
+ <xs:restriction>
+ <xs:simpleType>
+ <xs:list itemType="xs:ENTITY"/>
+ </xs:simpleType>
+ <xs:minLength value="1" id="ENTITIES.minLength"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="NMTOKEN" id="NMTOKEN">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#NMTOKEN"/>
+ </xs:annotation>
+ <xs:restriction base="xs:token">
+ <xs:pattern value="\c+" id="NMTOKEN.pattern">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/REC-xml#NT-Nmtoken">
+ pattern matches production 7 from the XML spec
+ </xs:documentation>
+ </xs:annotation>
+ </xs:pattern>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="NMTOKENS" id="NMTOKENS">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasFacet name="length"/>
+ <hfp:hasFacet name="minLength"/>
+ <hfp:hasFacet name="maxLength"/>
+ <hfp:hasFacet name="enumeration"/>
+ <hfp:hasFacet name="whiteSpace"/>
+ <hfp:hasFacet name="pattern"/>
+ <hfp:hasProperty name="ordered" value="false"/>
+ <hfp:hasProperty name="bounded" value="false"/>
+ <hfp:hasProperty name="cardinality" value="countably infinite"/>
+ <hfp:hasProperty name="numeric" value="false"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#NMTOKENS"/>
+ </xs:annotation>
+ <xs:restriction>
+ <xs:simpleType>
+ <xs:list itemType="xs:NMTOKEN"/>
+ </xs:simpleType>
+ <xs:minLength value="1" id="NMTOKENS.minLength"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Name" id="Name">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#Name"/>
+ </xs:annotation>
+ <xs:restriction base="xs:token">
+ <xs:pattern value="\i\c*" id="Name.pattern">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/REC-xml#NT-Name">
+ pattern matches production 5 from the XML spec
+ </xs:documentation>
+ </xs:annotation>
+ </xs:pattern>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="NCName" id="NCName">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#NCName"/>
+ </xs:annotation>
+ <xs:restriction base="xs:Name">
+ <xs:pattern value="[\i-[:]][\c-[:]]*" id="NCName.pattern">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/REC-xml-names/#NT-NCName">
+ pattern matches production 4 from the Namespaces in XML spec
+ </xs:documentation>
+ </xs:annotation>
+ </xs:pattern>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ID" id="ID">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#ID"/>
+ </xs:annotation>
+ <xs:restriction base="xs:NCName"/>
+ </xs:simpleType>
+ <xs:simpleType name="IDREF" id="IDREF">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#IDREF"/>
+ </xs:annotation>
+ <xs:restriction base="xs:NCName"/>
+ </xs:simpleType>
+ <xs:simpleType name="ENTITY" id="ENTITY">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#ENTITY"/>
+ </xs:annotation>
+ <xs:restriction base="xs:NCName"/>
+ </xs:simpleType>
+ <xs:simpleType name="integer" id="integer">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#integer"/>
+ </xs:annotation>
+ <xs:restriction base="xs:decimal">
+ <xs:fractionDigits value="0" fixed="true" id="integer.fractionDigits"/>
+ <xs:pattern value="[\-+]?[0-9]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="nonPositiveInteger" id="nonPositiveInteger">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#nonPositiveInteger"/>
+ </xs:annotation>
+ <xs:restriction base="xs:integer">
+ <xs:maxInclusive value="0" id="nonPositiveInteger.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="negativeInteger" id="negativeInteger">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#negativeInteger"/>
+ </xs:annotation>
+ <xs:restriction base="xs:nonPositiveInteger">
+ <xs:maxInclusive value="-1" id="negativeInteger.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="long" id="long">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasProperty name="bounded" value="true"/>
+ <hfp:hasProperty name="cardinality" value="finite"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#long"/>
+ </xs:annotation>
+ <xs:restriction base="xs:integer">
+ <xs:minInclusive value="-9223372036854775808" id="long.minInclusive"/>
+ <xs:maxInclusive value="9223372036854775807" id="long.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="int" id="int">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#int"/>
+ </xs:annotation>
+ <xs:restriction base="xs:long">
+ <xs:minInclusive value="-2147483648" id="int.minInclusive"/>
+ <xs:maxInclusive value="2147483647" id="int.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="short" id="short">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#short"/>
+ </xs:annotation>
+ <xs:restriction base="xs:int">
+ <xs:minInclusive value="-32768" id="short.minInclusive"/>
+ <xs:maxInclusive value="32767" id="short.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="byte" id="byte">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#byte"/>
+ </xs:annotation>
+ <xs:restriction base="xs:short">
+ <xs:minInclusive value="-128" id="byte.minInclusive"/>
+ <xs:maxInclusive value="127" id="byte.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="nonNegativeInteger" id="nonNegativeInteger">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#nonNegativeInteger"/>
+ </xs:annotation>
+ <xs:restriction base="xs:integer">
+ <xs:minInclusive value="0" id="nonNegativeInteger.minInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="unsignedLong" id="unsignedLong">
+ <xs:annotation>
+ <xs:appinfo>
+ <hfp:hasProperty name="bounded" value="true"/>
+ <hfp:hasProperty name="cardinality" value="finite"/>
+ </xs:appinfo>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#unsignedLong"/>
+ </xs:annotation>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:maxInclusive value="18446744073709551615" id="unsignedLong.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="unsignedInt" id="unsignedInt">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#unsignedInt"/>
+ </xs:annotation>
+ <xs:restriction base="xs:unsignedLong">
+ <xs:maxInclusive value="4294967295" id="unsignedInt.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="unsignedShort" id="unsignedShort">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#unsignedShort"/>
+ </xs:annotation>
+ <xs:restriction base="xs:unsignedInt">
+ <xs:maxInclusive value="65535" id="unsignedShort.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="unsignedByte" id="unsignedByte">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#unsignedByte"/>
+ </xs:annotation>
+ <xs:restriction base="xs:unsignedShort">
+ <xs:maxInclusive value="255" id="unsignedByte.maxInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="positiveInteger" id="positiveInteger">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#positiveInteger"/>
+ </xs:annotation>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:minInclusive value="1" id="positiveInteger.minInclusive"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="derivationControl">
+ <xs:annotation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="substitution"/>
+ <xs:enumeration value="extension"/>
+ <xs:enumeration value="restriction"/>
+ <xs:enumeration value="list"/>
+ <xs:enumeration value="union"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:group name="simpleDerivation">
+ <xs:choice>
+ <xs:element ref="xs:restriction"/>
+ <xs:element ref="xs:list"/>
+ <xs:element ref="xs:union"/>
+ </xs:choice>
+ </xs:group>
+ <xs:simpleType name="simpleDerivationSet">
+ <xs:annotation>
+ <xs:documentation>
+ #all or (possibly empty) subset of {restriction, union, list}
+ </xs:documentation>
+ <xs:documentation>
+ A utility type, not for public use</xs:documentation>
+ </xs:annotation>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="#all"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:list>
+ <xs:simpleType>
+ <xs:restriction base="xs:derivationControl">
+ <xs:enumeration value="list"/>
+ <xs:enumeration value="union"/>
+ <xs:enumeration value="restriction"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:list>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:complexType name="simpleType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:group ref="xs:simpleDerivation"/>
+ <xs:attribute name="final" type="xs:simpleDerivationSet"/>
+ <xs:attribute name="name" type="xs:NCName">
+ <xs:annotation>
+ <xs:documentation>
+ Can be restricted to required or forbidden
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="topLevelSimpleType">
+ <xs:complexContent>
+ <xs:restriction base="xs:simpleType">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:group ref="xs:simpleDerivation"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:NCName">
+ <xs:annotation>
+ <xs:documentation>
+ Required at the top level
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="localSimpleType">
+ <xs:complexContent>
+ <xs:restriction base="xs:simpleType">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ <xs:group ref="xs:simpleDerivation"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="prohibited">
+ <xs:annotation>
+ <xs:documentation>
+ Forbidden when nested
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="final" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="simpleType" type="xs:topLevelSimpleType" id="simpleType">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-simpleType"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:group name="facets">
+ <xs:annotation>
+ <xs:documentation>
+ We should use a substitution group for facets, but
+ that's ruled out because it would allow users to
+ add their own, which we're not ready for yet.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:choice>
+ <xs:element ref="xs:minExclusive"/>
+ <xs:element ref="xs:minInclusive"/>
+ <xs:element ref="xs:maxExclusive"/>
+ <xs:element ref="xs:maxInclusive"/>
+ <xs:element ref="xs:totalDigits"/>
+ <xs:element ref="xs:fractionDigits"/>
+ <xs:element ref="xs:length"/>
+ <xs:element ref="xs:minLength"/>
+ <xs:element ref="xs:maxLength"/>
+ <xs:element ref="xs:enumeration"/>
+ <xs:element ref="xs:whiteSpace"/>
+ <xs:element ref="xs:pattern"/>
+ </xs:choice>
+ </xs:group>
+ <xs:group name="simpleRestrictionModel">
+ <xs:sequence>
+ <xs:element name="simpleType" type="xs:localSimpleType" minOccurs="0"/>
+ <xs:group ref="xs:facets" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:group>
+ <xs:element name="restriction" id="restriction">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-restriction">
+ base attribute and simpleType child are mutually
+ exclusive, but one or other is required
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:group ref="xs:simpleRestrictionModel"/>
+ <xs:attribute name="base" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="list" id="list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-list">
+ itemType attribute and simpleType child are mutually
+ exclusive, but one or other is required
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:sequence>
+ <xs:element name="simpleType" type="xs:localSimpleType" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="itemType" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="union" id="union">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-union">
+ memberTypes attribute must be non-empty or there must be
+ at least one simpleType child
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:sequence>
+ <xs:element name="simpleType" type="xs:localSimpleType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="memberTypes" use="optional">
+ <xs:simpleType>
+ <xs:list itemType="xs:QName"/>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="facet">
+ <xs:complexContent>
+ <xs:extension base="xs:annotated">
+ <xs:attribute name="value" use="required"/>
+ <xs:attribute name="fixed" type="xs:boolean" use="optional" default="false"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="noFixedFacet">
+ <xs:complexContent>
+ <xs:restriction base="xs:facet">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="fixed" use="prohibited"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="minExclusive" id="minExclusive" type="xs:facet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-minExclusive"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="minInclusive" id="minInclusive" type="xs:facet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-minInclusive"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="maxExclusive" id="maxExclusive" type="xs:facet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-maxExclusive"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="maxInclusive" id="maxInclusive" type="xs:facet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-maxInclusive"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:complexType name="numFacet">
+ <xs:complexContent>
+ <xs:restriction base="xs:facet">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="value" type="xs:nonNegativeInteger" use="required"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="totalDigits" id="totalDigits">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-totalDigits"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="xs:numFacet">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="value" type="xs:positiveInteger" use="required"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="fractionDigits" id="fractionDigits" type="xs:numFacet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-fractionDigits"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="length" id="length" type="xs:numFacet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-length"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="minLength" id="minLength" type="xs:numFacet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-minLength"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="maxLength" id="maxLength" type="xs:numFacet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-maxLength"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="enumeration" id="enumeration" type="xs:noFixedFacet">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-enumeration"/>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="whiteSpace" id="whiteSpace">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-whiteSpace"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="xs:facet">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="value" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="preserve"/>
+ <xs:enumeration value="replace"/>
+ <xs:enumeration value="collapse"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pattern" id="pattern">
+ <xs:annotation>
+ <xs:documentation source="http://www.w3.org/TR/xmlschema-2/#element-pattern"/>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="xs:noFixedFacet">
+ <xs:sequence>
+ <xs:element ref="xs:annotation" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/CI/testxml/xsd/checkfile.sh b/CI/testxml/xsd/checkfile.sh
new file mode 100755
index 0000000..90df1f1
--- /dev/null
+++ b/CI/testxml/xsd/checkfile.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+xmllint --format --schema tmw.xsd "${1}" 2>&1 >/dev/null | \
+ grep -v ": Skipping import of schema located at " | \
+ grep -v ".xml validates"
diff --git a/CI/testxml/xsd/its.xsd b/CI/testxml/xsd/its.xsd
new file mode 100644
index 0000000..9dbb432
--- /dev/null
+++ b/CI/testxml/xsd/its.xsd
@@ -0,0 +1,926 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:its="http://www.w3.org/2005/11/its">
+ <!--
+ Schema generated from ODD source 2007-04-02T11:42:44+09:00. This schema has been developed using the ODD (One Document Does it
+ all) language of the Text Encoding Initiative (). This is a literate programming language for writing XML schemas, with three
+ characteristics: (1) The element and attribute set is specified using
+ an XML vocabulary which includes support for macros
+ (like DTD entities, or schema patterns), a hierarchical
+ class system for attributes and elements, and creation
+ of modules. (2) The content models for elements and attributes is
+ written using embedded RELAX NG XML notation. (3) Documentation for elements, attributes, value
+ lists etc. is written inline, along with examples and
+ other supporting material. XSLT transformations
+ are provided by the TEI to extract documentation in
+ HTML, XSL FO or LaTeX forms, and to generate RELAX NG
+ documents and DTD. From the RELAX NG documents, James
+ Clark's trang
+ can be used to create XML Schema documents.
+ -->
+ <xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="xlink.xsd"/>
+ <xs:element name="rules">
+ <xs:annotation>
+ <xs:documentation>Container for global rules.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-rules.content">
+ <xs:attributeGroup ref="its:its-rules.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-rules.content">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="its:translateRule"/>
+ <xs:element ref="its:locNoteRule"/>
+ <xs:element ref="its:termRule"/>
+ <xs:element ref="its:dirRule"/>
+ <xs:element ref="its:rubyRule"/>
+ <xs:element ref="its:langRule"/>
+ <xs:element ref="its:withinTextRule"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:attributeGroup name="its-rules.attributes">
+ <xs:attribute name="version" use="required" type="xs:float">
+ <xs:annotation>
+ <xs:documentation>Version of the ITS schema.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attributeGroup ref="xlink:its-type"/>
+ <xs:attributeGroup ref="xlink:its-href"/>
+ <!--
+ <xs:attribute ref="xlink:href"/>
+ <xs:attribute ref="xlink:type"/> -->
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-att.selector.attributes">
+ <xs:attributeGroup ref="its:att.selector.attribute.selector"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.selector.attribute.selector">
+ <xs:attribute name="selector" use="required" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>XPath expression identifying the nodes to be selected.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-att.version.attributes">
+ <xs:attributeGroup ref="its:att.version.attribute.version"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.version.attribute.version">
+ <xs:attribute name="version" use="required" form="qualified" type="xs:float">
+ <xs:annotation>
+ <xs:documentation>Version of the ITS schema.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-att.local.no-ns.attributes">
+ <xs:attributeGroup ref="its:att.local.no-ns.attribute.translate"/>
+ <xs:attributeGroup ref="its:att.local.no-ns.attribute.locNote"/>
+ <xs:attributeGroup ref="its:att.local.no-ns.attribute.locNoteType"/>
+ <xs:attributeGroup ref="its:att.local.no-ns.attribute.locNoteRef"/>
+ <xs:attributeGroup ref="its:att.local.no-ns.attribute.termInfoRef"/>
+ <xs:attributeGroup ref="its:att.local.no-ns.attribute.term"/>
+ <xs:attributeGroup ref="its:att.local.no-ns.attribute.dir"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.no-ns.attribute.translate">
+ <xs:attribute name="translate">
+ <xs:annotation>
+ <xs:documentation>The Translate data category information to be attached to
+ the current node.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The nodes need to be translated.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The nodes must not be translated.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.no-ns.attribute.locNote">
+ <xs:attribute name="locNote" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.no-ns.attribute.locNoteType">
+ <xs:attribute name="locNoteType">
+ <xs:annotation>
+ <xs:documentation>The type of localization note.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="alert">
+ <xs:annotation>
+ <xs:documentation>Localization note is an alert.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="description">
+ <xs:annotation>
+ <xs:documentation>Localization note is a description.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.no-ns.attribute.locNoteRef">
+ <xs:attribute name="locNoteRef" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>URI referring to the location of the localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.no-ns.attribute.termInfoRef">
+ <xs:attribute name="termInfoRef" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>Pointer to a resource containing
+ information about the term.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.no-ns.attribute.term">
+ <xs:attribute name="term">
+ <xs:annotation>
+ <xs:documentation>Indicates a term locally.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The value 'yes' means that this is a term.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The value 'no' means that this is not a term.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.no-ns.attribute.dir">
+ <xs:attribute name="dir">
+ <xs:annotation>
+ <xs:documentation>The text direction for the context.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="ltr">
+ <xs:annotation>
+ <xs:documentation>Left-to-right text.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="rtl">
+ <xs:annotation>
+ <xs:documentation>Right-to-left text.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="lro">
+ <xs:annotation>
+ <xs:documentation>Left-to-right override.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="rlo">
+ <xs:annotation>
+ <xs:documentation>Right-to-left override.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-att.local.with-ns.attributes">
+ <xs:attributeGroup ref="its:att.local.with-ns.attribute.translate"/>
+ <xs:attributeGroup ref="its:att.local.with-ns.attribute.locNote"/>
+ <xs:attributeGroup ref="its:att.local.with-ns.attribute.locNoteType"/>
+ <xs:attributeGroup ref="its:att.local.with-ns.attribute.locNoteRef"/>
+ <xs:attributeGroup ref="its:att.local.with-ns.attribute.termInfoRef"/>
+ <xs:attributeGroup ref="its:att.local.with-ns.attribute.term"/>
+ <xs:attributeGroup ref="its:att.local.with-ns.attribute.dir"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.with-ns.attribute.translate">
+ <xs:attribute name="translate" form="qualified">
+ <xs:annotation>
+ <xs:documentation>The Translate data category information to be attached to
+ the current node.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The nodes need to be translated.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The nodes must not be translated.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.with-ns.attribute.locNote">
+ <xs:attribute name="locNote" form="qualified" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.with-ns.attribute.locNoteType">
+ <xs:attribute name="locNoteType" form="qualified">
+ <xs:annotation>
+ <xs:documentation>The type of localization note.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="alert">
+ <xs:annotation>
+ <xs:documentation>Localization note is an alert.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="description">
+ <xs:annotation>
+ <xs:documentation>Localization note is a description.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.with-ns.attribute.locNoteRef">
+ <xs:attribute name="locNoteRef" form="qualified" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>URI referring to the location of the localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.with-ns.attribute.termInfoRef">
+ <xs:attribute name="termInfoRef" form="qualified" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>Pointer to a resource containing
+ information about the term.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.with-ns.attribute.term">
+ <xs:attribute name="term" form="qualified">
+ <xs:annotation>
+ <xs:documentation>Indicates a term locally.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The value 'yes' means that this is a term.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The value 'no' means that this is not a term.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.local.with-ns.attribute.dir">
+ <xs:attribute name="dir" form="qualified">
+ <xs:annotation>
+ <xs:documentation>The text direction for the context.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="ltr">
+ <xs:annotation>
+ <xs:documentation>Left-to-right text.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="rtl">
+ <xs:annotation>
+ <xs:documentation>Right-to-left text.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="lro">
+ <xs:annotation>
+ <xs:documentation>Left-to-right override.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="rlo">
+ <xs:annotation>
+ <xs:documentation>Right-to-left override.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="span">
+ <xs:annotation>
+ <xs:documentation>Inline element to contain ITS information.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-span.content">
+ <xs:attributeGroup ref="its:its-span.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-span.content" mixed="true">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="its:ruby"/>
+ <xs:element ref="its:span"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:attributeGroup name="its-span.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ </xs:attributeGroup>
+ <xs:element name="translateRule">
+ <xs:annotation>
+ <xs:documentation>Rule about the Translate data category.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attributeGroup ref="its:its-translateRule.attributes"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="its-translateRule.attributes">
+ <xs:attributeGroup ref="its:its-att.selector.attributes"/>
+ <xs:attribute name="translate" use="required">
+ <xs:annotation>
+ <xs:documentation>The Translate data category information to be
+ applied to selected nodes.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The nodes need to be translated.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The nodes must not be translated.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-att.translate.attributes">
+ <xs:attributeGroup ref="its:att.translate.attribute.translate"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.translate.attribute.translate">
+ <xs:attribute name="translate" form="qualified">
+ <xs:annotation>
+ <xs:documentation>The Translate data category information to be attached to
+ the current node.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The nodes need to be translated.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The nodes must not be translated.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="locNoteRule">
+ <xs:annotation>
+ <xs:documentation>Rule about the Localization Note data category.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-locNoteRule.content">
+ <xs:attributeGroup ref="its:its-locNoteRule.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-locNoteRule.content">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="its:locNote"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:attributeGroup name="its-locNoteRule.attributes">
+ <xs:attributeGroup ref="its:its-att.selector.attributes"/>
+ <xs:attribute name="locNotePointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that holds the localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="locNoteType" use="required">
+ <xs:annotation>
+ <xs:documentation>The type of localization note.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="alert">
+ <xs:annotation>
+ <xs:documentation>Localization note is an alert.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="description">
+ <xs:annotation>
+ <xs:documentation>Localization note is a description.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="locNoteRef" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>URI referring to the location of the localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="locNoteRefPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that holds the URI referring to the location of the localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="locNote">
+ <xs:annotation>
+ <xs:documentation>Contains a localization note.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-locNote.content">
+ <xs:attributeGroup ref="its:its-locNote.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-locNote.content" mixed="true">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="its:ruby"/>
+ <xs:element ref="its:span"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:attributeGroup name="its-locNote.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-att.locNote.attributes">
+ <xs:attributeGroup ref="its:att.locNote.attribute.locNote"/>
+ <xs:attributeGroup ref="its:att.locNote.attribute.locNoteType"/>
+ <xs:attributeGroup ref="its:att.locNote.attribute.locNoteRef"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.locNote.attribute.locNote">
+ <xs:attribute name="locNote" form="qualified" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.locNote.attribute.locNoteType">
+ <xs:attribute name="locNoteType" form="qualified">
+ <xs:annotation>
+ <xs:documentation>The type of localization note.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="alert">
+ <xs:annotation>
+ <xs:documentation>Localization note is an alert.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="description">
+ <xs:annotation>
+ <xs:documentation>Localization note is a description.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.locNote.attribute.locNoteRef">
+ <xs:attribute name="locNoteRef" form="qualified" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>URI referring to the location of the localization note.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="termRule">
+ <xs:annotation>
+ <xs:documentation>Rule about the Terminology data category.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attributeGroup ref="its:its-termRule.attributes"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="its-termRule.attributes">
+ <xs:attributeGroup ref="its:its-att.selector.attributes"/>
+ <xs:attribute name="term" use="required">
+ <xs:annotation>
+ <xs:documentation>Indicates whether the selection is a term or not.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The value 'yes' means that this is a term.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The value 'no' means that this is not a term.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="termInfoRef" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>URI referring to the resource providing information about the term.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="termInfoRefPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node containing a URI referring to the resource providing information about the term.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="termInfoPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node containing
+ information about the term.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-att.term.attributes">
+ <xs:attributeGroup ref="its:att.term.attribute.termInfoRef"/>
+ <xs:attributeGroup ref="its:att.term.attribute.term"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.term.attribute.termInfoRef">
+ <xs:attribute name="termInfoRef" form="qualified" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>Pointer to a resource containing
+ information about the term.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.term.attribute.term">
+ <xs:attribute name="term" form="qualified">
+ <xs:annotation>
+ <xs:documentation>Indicates a term locally.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The value 'yes' means that this is a term.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The value 'no' means that this is not a term.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="dirRule">
+ <xs:annotation>
+ <xs:documentation>Rule about the Directionality data category.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attributeGroup ref="its:its-dirRule.attributes"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="its-dirRule.attributes">
+ <xs:attributeGroup ref="its:its-att.selector.attributes"/>
+ <xs:attribute name="dir" use="required">
+ <xs:annotation>
+ <xs:documentation>The text direction for the selection.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="ltr">
+ <xs:annotation>
+ <xs:documentation>Left-to-right text.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="rtl">
+ <xs:annotation>
+ <xs:documentation>Right-to-left text.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="lro">
+ <xs:annotation>
+ <xs:documentation>Left-to-right override.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="rlo">
+ <xs:annotation>
+ <xs:documentation>Right-to-left override.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-att.dir.attributes">
+ <xs:attributeGroup ref="its:att.dir.attribute.dir"/>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="att.dir.attribute.dir">
+ <xs:attribute name="dir" form="qualified">
+ <xs:annotation>
+ <xs:documentation>The text direction for the context.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="ltr">
+ <xs:annotation>
+ <xs:documentation>Left-to-right text.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="rtl">
+ <xs:annotation>
+ <xs:documentation>Right-to-left text.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="lro">
+ <xs:annotation>
+ <xs:documentation>Left-to-right override.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="rlo">
+ <xs:annotation>
+ <xs:documentation>Right-to-left override.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="rubyRule">
+ <xs:annotation>
+ <xs:documentation>Rule about the Ruby data category.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-rubyRule.content">
+ <xs:attributeGroup ref="its:its-rubyRule.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-rubyRule.content">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="its:rubyText"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:attributeGroup name="its-rubyRule.attributes">
+ <xs:attributeGroup ref="its:its-att.selector.attributes"/>
+ <xs:attribute name="rubyPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that corresponds to a ruby element</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="rtPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that
+ corresponds to a rt element</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="rpPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that
+ corresponds to a rp element</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="rbcPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that
+ corresponds to a rbc element</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="rtcPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that
+ corresponds to a rtc element</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="rbspanPointer" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that corresponds to a rbspan attribute.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="rubyText">
+ <xs:annotation>
+ <xs:documentation>Ruby text.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType mixed="true">
+ <xs:attributeGroup ref="its:its-rubyText.attributes"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="its-rubyText.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ <xs:attribute name="rbspan" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Allows an rt element to span multiple rb elements in complex ruby markup.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="ruby">
+ <xs:annotation>
+ <xs:documentation>Ruby markup.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-ruby.content">
+ <xs:attributeGroup ref="its:its-ruby.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-ruby.content">
+ <xs:choice>
+ <xs:sequence>
+ <xs:element ref="its:rb"/>
+ <xs:choice>
+ <xs:element ref="its:rt"/>
+ <xs:sequence>
+ <xs:element ref="its:rp"/>
+ <xs:element ref="its:rt"/>
+ <xs:element ref="its:rp"/>
+ </xs:sequence>
+ </xs:choice>
+ </xs:sequence>
+ <xs:sequence>
+ <xs:element ref="its:rbc"/>
+ <xs:element ref="its:rtc"/>
+ <xs:element minOccurs="0" ref="its:rtc"/>
+ </xs:sequence>
+ </xs:choice>
+ </xs:complexType>
+ <xs:attributeGroup name="its-ruby.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ </xs:attributeGroup>
+ <xs:element name="rb">
+ <xs:annotation>
+ <xs:documentation>Ruby base text.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-rb.content">
+ <xs:attributeGroup ref="its:its-rb.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-rb.content" mixed="true">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="its:span"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:attributeGroup name="its-rb.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ </xs:attributeGroup>
+ <xs:element name="rt">
+ <xs:annotation>
+ <xs:documentation>Ruby text.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-rt.content">
+ <xs:attributeGroup ref="its:its-rt.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-rt.content" mixed="true">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="its:span"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:attributeGroup name="its-rt.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ <xs:attribute name="rbspan" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Allows an rt element to span multiple rb elements in complex ruby markup.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="rbc">
+ <xs:annotation>
+ <xs:documentation>Container for rb elements in the case of complex ruby markup.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-rbc.content">
+ <xs:attributeGroup ref="its:its-rbc.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-rbc.content">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" ref="its:rb"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:attributeGroup name="its-rbc.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ </xs:attributeGroup>
+ <xs:element name="rtc">
+ <xs:annotation>
+ <xs:documentation>Container for rt elements in the case of complex ruby markup. </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="its:its-rtc.content">
+ <xs:attributeGroup ref="its:its-rtc.attributes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="its-rtc.content">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" ref="its:rt"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:attributeGroup name="its-rtc.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ </xs:attributeGroup>
+ <xs:element name="rp">
+ <xs:annotation>
+ <xs:documentation>Used in the case of simple ruby markup to specify characters that can denote the beginning and end of ruby text when user agents do not have other ways to present ruby text distinctively from the base text.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType mixed="true">
+ <xs:attributeGroup ref="its:its-rp.attributes"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="its-rp.attributes">
+ <xs:attributeGroup ref="its:its-att.local.no-ns.attributes"/>
+ </xs:attributeGroup>
+ <xs:element name="langRule">
+ <xs:annotation>
+ <xs:documentation>Rule about the Language Information data category.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attributeGroup ref="its:its-langRule.attributes"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="its-langRule.attributes">
+ <xs:attributeGroup ref="its:its-att.selector.attributes"/>
+ <xs:attribute name="langPointer" use="required" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Relative XPath expression pointing to a node that contains language information.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:element name="withinTextRule">
+ <xs:annotation>
+ <xs:documentation>Rule about the Elements Within Text data category.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attributeGroup ref="its:its-withinTextRule.attributes"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="its-withinTextRule.attributes">
+ <xs:attributeGroup ref="its:its-att.selector.attributes"/>
+ <xs:attribute name="withinText" use="required">
+ <xs:annotation>
+ <xs:documentation>States whether current context is regarded as
+ "within text".</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="yes">
+ <xs:annotation>
+ <xs:documentation>The element and its content are part of the flow of its parent element.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="no">
+ <xs:annotation>
+ <xs:documentation>The element splits the text flow of its parent element and its content is an independent text flow.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="nested">
+ <xs:annotation>
+ <xs:documentation>The element is part of the flow of its parent element, its content is an independent flow.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+</xs:schema>
diff --git a/CI/testxml/xsd/tmw.xsd b/CI/testxml/xsd/tmw.xsd
new file mode 100644
index 0000000..a8b5cf2
--- /dev/null
+++ b/CI/testxml/xsd/tmw.xsd
@@ -0,0 +1,2117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) -2016 The Mana World Development Team
+ Copyright (C) 2016 Evol Online developers
+ Copyright (C) 2020 TMW2: Moubootaur Legends Team
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:its="http://www.w3.org/2005/11/its" elementFormDefault="qualified">
+ <xs:import namespace="http://www.w3.org/2005/11/its" schemaLocation="its.xsd"/>
+ <!-- stuff up here is used everywhere-->
+ <xs:element name="include" type="include"/>
+ <xs:complexType name="include">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="empty"/>
+ <!--
+ XML::getBoolProperty
+ -->
+ <xs:simpleType name="bool">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="true"/>
+ <xs:enumeration value="false"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- roots, with their children nearby -->
+ <!--
+ EffectManager::loadXmlFile
+ effectsFile: effects.xml
+ effectsPatchFile: effects_patch.xml
+ effectsPatchDir: effects.d/*.xml
+ -->
+ <xs:element name="being-effects" type="root_being-effects"/>
+ <xs:complexType name="root_being-effects">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="effect">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="particle" type="xs:string" use="optional"/>
+ <xs:attribute name="audio" type="xs:string" use="optional"/>
+ <xs:attribute name="sprite" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!--
+ Configuration::init/ConfigurationObject::initFromXML
+ branding
+ portable.xml
+ command-line
+ config
+ <configdir>/test.xml
+ <configdir>/config.xml
+ serverConfig
+ <configdir>/<server>/config.xml
+ paths
+ paths.xml
+ features
+ featuresFile features.xml
+ -->
+ <xs:element name="configuration" type="root_configuration"/>
+ <xs:complexType name="root_configuration">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="list">
+ <xs:complexType>
+ <!-- what manaplus does is actually impossible to represent -->
+ <!-- TODO in a future version fix this horrible abuse of XML -->
+ <xs:choice>
+ <xs:element name="nested_conf_1" type="root_configuration" maxOccurs="unbounded"/>
+ <xs:element name="nested_conf_2" type="root_configuration" maxOccurs="unbounded"/>
+ </xs:choice>
+ <xs:attribute name="name" type="nested_configuration" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="option">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="nested_configuration">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="nested_conf_1"/>
+ <xs:enumeration value="nested_conf_2"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!--
+ Particle::addEffect(file|dye, x, y, rot)
+ -->
+ <xs:element name="effect" type="root_effect"/>
+ <xs:complexType name="root_effect">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="particle">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:group ref="particle_extras" minOccurs="0" maxOccurs="unbounded"/>
+ <!-- this should probably be required to go first -->
+ <xs:choice minOccurs="0">
+ <xs:element name="animation" type="animation_1"/>
+ <xs:element name="rotation" type="animation_1"/>
+ <xs:element name="image" type="xs:string"/>
+ </xs:choice>
+ <xs:group ref="particle_extras" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="position-x" type="xs:float" default="0"/>
+ <xs:attribute name="position-y" type="xs:float" default="0"/>
+ <xs:attribute name="position-z" type="xs:float" default="0"/>
+ <!-- TODO is this really? It was so unusual, but it's common. -->
+ <xs:attribute name="lifetime" type="xs:int" use="optional"/>
+ <xs:attribute name="size-adjustable" type="bool" default="false"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:group name="particle_extras">
+ <xs:choice>
+ <xs:element name="emitter" type="particle_emitter"/>
+ <xs:element name="deatheffect" type="death_effect"/>
+ </xs:choice>
+ </xs:group>
+ <xs:complexType name="death_effect">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="on-floor" type="bool" default="true"/>
+ <xs:attribute name="on-sky" type="bool" default="true"/>
+ <xs:attribute name="on-other" type="bool" default="false"/>
+ <xs:attribute name="on-impact" type="bool" default="true"/>
+ <xs:attribute name="on-timeout" type="bool" default="true"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <!--
+ SimpleAnimation::initializeAnimation
+ -->
+ <xs:complexType name="animation_1">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="frame">
+ <xs:complexType>
+ <xs:attributeGroup ref="frame_or_sequence_attrs"/>
+ <xs:attribute name="index" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sequence">
+ <xs:complexType>
+ <xs:attributeGroup ref="frame_or_sequence_attrs"/>
+ <xs:attribute name="start" type="xs:int" use="required"/>
+ <xs:attribute name="end" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="end" type="empty"/>
+ </xs:choice>
+ <xs:attribute name="imageset" type="xs:string" use="required"/>
+ <xs:attribute name="width" type="xs:int" use="required"/>
+ <xs:attribute name="height" type="xs:int" use="required"/>
+ </xs:complexType>
+ <!--
+ ParticleEmitter::ParticleEmitter
+ -->
+ <xs:complexType name="animation_2">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="frame">
+ <xs:complexType>
+ <xs:attributeGroup ref="frame_or_sequence_attrs"/>
+ <xs:attribute name="index" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sequence">
+ <xs:complexType>
+ <xs:attributeGroup ref="frame_or_sequence_attrs"/>
+ <xs:attribute name="start" type="xs:int" use="required"/>
+ <xs:attribute name="end" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="end" type="empty"/>
+ </xs:choice>
+ <xs:attribute name="imageset" type="xs:string" use="required"/>
+ <xs:attribute name="width" type="xs:int" use="required"/>
+ <xs:attribute name="height" type="xs:int" use="required"/>
+ <xs:attribute name="subX" type="xs:int" use="optional"/>
+ <xs:attribute name="subY" type="xs:int" use="optional"/>
+ <xs:attribute name="subWidth" type="xs:int" use="optional"/>
+ <xs:attribute name="subHeight" type="xs:int" use="optional"/>
+ </xs:complexType>
+ <!--
+ SpriteDef::loadAnimation
+ -->
+ <xs:complexType name="animation_3">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="frame">
+ <xs:complexType>
+ <xs:attributeGroup ref="frame_or_sequence_attrs"/>
+ <xs:attribute name="index" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sequence">
+ <xs:complexType>
+ <xs:attributeGroup ref="frame_or_sequence_attrs"/>
+ <xs:attribute name="start" type="xs:int" use="optional"/>
+ <xs:attribute name="end" type="xs:int" use="optional"/>
+ <xs:attribute name="value" type="xs:string" use="optional"/>
+ <xs:attribute name="repeat" type="xs:int" default="1"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="end" type="empty"/>
+ <xs:element name="jump">
+ <xs:complexType>
+ <xs:attribute name="action" type="xs:string" use="required"/>
+ <xs:attribute name="rand" type="xs:int" default="100"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="label">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="goto">
+ <xs:complexType>
+ <xs:attribute name="label" type="xs:string" use="required"/>
+ <xs:attribute name="rand" type="xs:int" default="100"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="direction" default="default">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="up"/>
+ <xs:enumeration value="left"/>
+ <xs:enumeration value="right"/>
+ <xs:enumeration value="down"/>
+ <xs:enumeration value="upleft"/>
+ <xs:enumeration value="upright"/>
+ <xs:enumeration value="downleft"/>
+ <xs:enumeration value="downright"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ <xs:attributeGroup name="frame_or_sequence_attrs">
+ <xs:attribute name="delay" type="xs:int" default="0"/>
+ <xs:attribute name="offsetX" type="xs:int" default="0"/>
+ <xs:attribute name="offsetY" type="xs:int" default="0"/>
+ <xs:attribute name="rand" type="xs:int" default="100"/>
+ </xs:attributeGroup>
+ <!--
+ ParticleEmitter::ParticleEmitter
+ -->
+ <xs:complexType name="particle_emitter">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="property">
+ <xs:complexType>
+ <!-- TODO in a future version fix this horrible abuse of XML -->
+ <xs:attribute name="name" type="particle_property" use="required"/>
+ <!-- type varies depending on property -->
+ <xs:attribute name="value" type="xs:string" use="optional"/>
+ <xs:attribute name="min" type="xs:float" use="optional"/>
+ <xs:attribute name="max" type="xs:float" use="optional"/>
+ <xs:attribute name="change-func" default="none">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="saw"/>
+ <xs:enumeration value="sawtooth"/>
+ <xs:enumeration value="sine"/>
+ <xs:enumeration value="sinewave"/>
+ <xs:enumeration value="triangle"/>
+ <xs:enumeration value="square"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="change-amplitude" type="xs:float" use="optional"/>
+ <xs:attribute name="change-period" type="xs:int" use="optional"/>
+ <xs:attribute name="change-phase" type="xs:int" use="optional"/>
+ <!-- only for subimage -->
+ <xs:attribute name="x" type="xs:int" use="optional"/>
+ <xs:attribute name="y" type="xs:int" use="optional"/>
+ <xs:attribute name="width" type="xs:int" use="optional"/>
+ <xs:attribute name="height" type="xs:int" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="emitter" type="particle_emitter"/>
+ <xs:element name="rotation" type="animation_2"/>
+ <xs:element name="animation" type="animation_2"/>
+ <xs:element name="deatheffect" type="death_effect"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:simpleType name="particle_property">
+ <xs:restriction base="xs:string">
+ <!-- xs:float -->
+ <xs:enumeration value="position-x"/>
+ <!-- xs:float -->
+ <xs:enumeration value="position-y"/>
+ <!-- xs:float -->
+ <xs:enumeration value="position-z"/>
+ <!-- xs:string -->
+ <xs:enumeration value="image"/>
+ <!-- xs:string for value, also xs:int for x/w/width/height -->
+ <xs:enumeration value="subimage"/>
+ <!-- xs:float -->
+ <xs:enumeration value="horizontal-angle"/>
+ <!-- xs:float -->
+ <xs:enumeration value="vertical-angle"/>
+ <!-- xs:float -->
+ <xs:enumeration value="power"/>
+ <!-- xs:float -->
+ <xs:enumeration value="gravity"/>
+ <!-- xs:int -->
+ <xs:enumeration value="randomness"/>
+ <!-- xs:int -->
+ <xs:enumeration value="randomnes"/>
+ <!-- xs:float -->
+ <xs:enumeration value="bounce"/>
+ <!-- xs:int -->
+ <xs:enumeration value="lifetime"/>
+ <!-- xs:int -->
+ <xs:enumeration value="output"/>
+ <!-- xs:int -->
+ <xs:enumeration value="output-pause"/>
+ <!-- xs:float -->
+ <xs:enumeration value="acceleration"/>
+ <!-- xs:float -->
+ <xs:enumeration value="die-distance"/>
+ <!-- xs:float -->
+ <xs:enumeration value="momentum"/>
+ <!-- xs:int -->
+ <xs:enumeration value="fade-out"/>
+ <!-- xs:int -->
+ <xs:enumeration value="fade-in"/>
+ <!-- xs:float -->
+ <xs:enumeration value="alpha"/>
+ <!-- ignored -->
+ <xs:enumeration value="follow-parent"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!--
+ QuestsWindow::loadXmlFile
+ questsFile: quests.xml
+ questsPatchFile: quests_patch.xml
+ questsPatchDir: quests.d/*.xml
+ -->
+ <xs:element name="quests" type="root_quests"/>
+ <xs:complexType name="root_quests">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="var">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="quest" type="quests_var_quest"/>
+ <xs:element name="effect" type="quests_var_effect"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="nowiki" type="xs:int" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!--
+ QuestsWindow::loadQuest
+ -->
+ <xs:complexType name="quests_var_quest">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="text" type="quests_quest_text"/>
+ <xs:element name="name" type="xs:string"/>
+ <xs:element name="reward" type="quests_quest_text"/>
+ <xs:element name="giver" type="xs:string"/>
+ <xs:element name="questgiver" type="xs:string"/>
+ <xs:element name="coordinates" type="quests_quest_coordinates"/>
+ <xs:element name="npc" type="xs:string"/>
+ <xs:element name="level" type="xs:string"/>
+ <xs:element name="wiki" type="xs:string"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="group" type="xs:string" use="required"/>
+ <!--
+ For all known quests, exactly one of these is provided, with a single
+ integer value. However, manaplus actually parses both, and as a
+ comma-separated list. (xsd spec says they should be space-separated).
+ -->
+ <!-- TODO fix this horrible abuse of XML-->
+ <xs:attribute name="complete" type="xs:string" use="optional"/>
+ <xs:attribute name="incomplete" type="xs:string" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="quests_quest_coordinates">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="x" type="xs:int" use="required"/>
+ <xs:attribute name="y" type="xs:int" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="quests_quest_text">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="text1" type="xs:string" use="optional"/>
+ <xs:attribute name="text2" type="xs:string" use="optional"/>
+ <xs:attribute name="text3" type="xs:string" use="optional"/>
+ <xs:attribute name="text4" type="xs:string" use="optional"/>
+ <xs:attribute name="text5" type="xs:string" use="optional"/>
+ <xs:attribute name="text6" type="xs:string" use="optional"/>
+ <xs:attribute name="text7" type="xs:string" use="optional"/>
+ <xs:attribute name="text8" type="xs:string" use="optional"/>
+ <xs:attribute name="text9" type="xs:string" use="optional"/>
+ <xs:attribute name="text10" type="xs:string" use="optional"/>
+ <xs:attribute name="text11" type="xs:string" use="optional"/>
+ <xs:attribute name="text12" type="xs:string" use="optional"/>
+ <xs:attribute name="text13" type="xs:string" use="optional"/>
+ <xs:attribute name="text14" type="xs:string" use="optional"/>
+ <xs:attribute name="text15" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <!--
+ QuestsWindow::loadEffect
+ -->
+ <xs:complexType name="quests_var_effect">
+ <xs:attribute name="map" type="xs:string" use="required"/>
+ <xs:attribute name="npc" type="xs:int" use="required"/>
+ <xs:attribute name="effect" type="xs:int" use="required"/>
+ <!-- Really a comma-separated list, but xsd wants space-separated -->
+ <!-- TODO fix this horrible abuse of XML-->
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ <!--
+ SkillDialog::loadXmlFile
+ skillsFile or skillsFile2: skills.xml or ea-skills.xml (but these were backwards before v1.4.1.18)
+ skillsPatchFile: skills_patch.xml
+ skillsPatchDir: skills.d/*.xml
+ -->
+ <xs:simpleType name="skillType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="list"/>
+ <xs:enumeration value="vertical"/>
+ <xs:enumeration value="rectangle"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="skills" type="root_skills"/>
+ <xs:complexType name="root_skills">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="set">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="skill">
+ <xs:complexType>
+ <!-- By code, sometimes 'id' is 'var', but I don't see it in the wild. -->
+ <xs:attribute name="id" type="xs:int" default="-1"/>
+ <xs:attribute name="var" type="xs:int" default="-1"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="useButton" type="xs:string" default="Use"/>
+ <xs:attribute name="owner" type="xs:string" use="optional" default="player"/>
+ <xs:attribute name="errorText" type="xs:string" use="optional"/>
+ <xs:attribute name="alwaysVisible" type="bool" use="optional" default="false"/>
+ <xs:attribute name="castingSrcEffectId" type="xs:string" use="optional"/>
+ <xs:attribute name="castingDstEffectId" type="xs:string" use="optional"/>
+ <xs:attribute name="castingGroundEffectId" type="xs:string" use="optional"/>
+ <xs:attribute name="castingAction" type="xs:string" use="optional"/>
+ <xs:attribute name="castingRideAction" type="xs:string" use="optional"/>
+ <xs:attribute name="castingSkyAction" type="xs:string" use="optional"/>
+ <xs:attribute name="castingWaterAction" type="xs:string" use="optional"/>
+ <xs:attribute name="castingAnimation" type="xs:string" use="optional"/>
+ <xs:attribute name="castingMissile-particle" type="xs:string" use="optional"/>
+ <xs:attribute name="castingMissile-z" type="xs:float" use="optional"/>
+ <xs:attribute name="castingMissile-lifetime" type="xs:int" use="optional"/>
+ <xs:attribute name="castingMissile-speed" type="xs:float" use="optional"/>
+ <xs:attribute name="castingMissile-diedistance" type="xs:float" use="optional"/>
+ <xs:attribute name="missile-particle" type="xs:string" use="optional"/>
+ <xs:attribute name="missile-z" type="xs:float" use="optional"/>
+ <xs:attribute name="missile-lifetime" type="xs:int" use="optional"/>
+ <xs:attribute name="missile-speed" type="xs:float" use="optional"/>
+ <xs:attribute name="missile-diedistance" type="xs:float" use="optional"/>
+ <xs:attribute name="useTextParameter" type="bool" default="false"/>
+ <xs:attribute name="icon" type="xs:string" use="optional"/>
+ <xs:attribute name="level" type="xs:int" default="0"/>
+ <xs:attribute name="shortName" type="xs:string" use="optional"/>
+ <xs:attribute name="description" type="xs:string" use="optional"/>
+ <xs:attribute name="soundHit" type="xs:string" use="optional"/>
+ <xs:attribute name="soundHitDelay" type="xs:int" use="optional"/>
+ <xs:attribute name="soundMiss" type="xs:string" use="optional"/>
+ <xs:attribute name="soundMissDelay" type="xs:int" use="optional"/>
+ <xs:attribute name="invokeCmd" type="xs:string" use="optional"/>
+ <xs:attribute name="levelUpEffectId" type="xs:int" use="optional"/>
+ <xs:attribute name="removeEffectId" type="xs:int" use="optional"/>
+ <xs:attribute name="hitEffectId" type="xs:int" use="optional"/>
+ <xs:attribute name="missEffectId" type="xs:int" use="optional"/>
+ <xs:attribute name="srcEffectId" type="xs:string" use="optional"/>
+ <xs:attribute name="dstEffectId" type="xs:string" use="optional"/>
+ <xs:attribute name="x" type="xs:int" use="optional"/>
+ <xs:attribute name="y" type="xs:int" use="optional"/>
+ <xs:attribute name="autoTab" type="bool" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="type" type="skillType" default="vertical"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!--
+ SkillUnitDb::load
+ -->
+ <xs:element name="skillunits" type="root_skillunits"/>
+ <xs:complexType name="root_skillunits">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="skillunit">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="particlefx" type="xs:string"/>
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" default="skill"/>
+ <xs:attribute name="targetSelection" type="bool" default="true"/>
+ <xs:attributeGroup ref="being_basic_attributes"/>
+ <xs:attribute name="deadSortOffsetY" type="xs:int" default="31"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!--
+ EquipmentWindow::fillBoxes
+ equipmentWindowFile: equipmentwindow.xml
+ -->
+ <xs:element name="equipment" type="root_equipment"/>
+ <xs:complexType name="root_equipment">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="page" type="equipment_page"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="image" type="xs:string" default="equipmentbox.png"/>
+ </xs:complexType>
+
+ <!--
+ EquipmentWindow::loadPage
+ -->
+ <xs:complexType name="equipment_page">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="playerbox" type="equipment_playerbox"/>
+ <xs:element name="slot" type="equipment_slot"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string"/>
+ </xs:complexType>
+
+ <!--
+ EquipmentWindow::loadPlayerBox
+ -->
+ <xs:complexType name="equipment_playerbox">
+ <xs:attribute name="x" type="xs:int" use="required"/>
+ <xs:attribute name="y" type="xs:int" use="required"/>
+ <xs:attribute name="width" type="xs:int" use="required"/>
+ <xs:attribute name="height" type="xs:int" use="required"/>
+ </xs:complexType>
+ <!--
+ EquipmentWindow::loadSlot
+ -->
+ <xs:complexType name="equipment_slot">
+ <xs:attribute name="name" type="equipment_slot_name" use="required"/>
+ <xs:attribute name="x" type="xs:int" use="required"/>
+ <xs:attribute name="y" type="xs:int" use="required"/>
+ <xs:attribute name="image" type="xs:int" default="0"/>
+ </xs:complexType>
+ <xs:simpleType name="equipment_slot_name">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="topclothes"/>
+ <xs:enumeration value="top"/>
+ <xs:enumeration value="torso"/>
+ <xs:enumeration value="body"/>
+ <xs:enumeration value="slot0"/>
+ <xs:enumeration value="glove"/>
+ <xs:enumeration value="gloves"/>
+ <xs:enumeration value="slot1"/>
+ <xs:enumeration value="hat"/>
+ <xs:enumeration value="hats"/>
+ <xs:enumeration value="slot2"/>
+ <xs:enumeration value="bottomclothes"/>
+ <xs:enumeration value="bottom"/>
+ <xs:enumeration value="pants"/>
+ <xs:enumeration value="slot3"/>
+ <xs:enumeration value="shoes"/>
+ <xs:enumeration value="boot"/>
+ <xs:enumeration value="boots"/>
+ <xs:enumeration value="slot4"/>
+ <xs:enumeration value="misc1"/>
+ <xs:enumeration value="cape"/>
+ <xs:enumeration value="slot5"/>
+ <xs:enumeration value="wings"/>
+ <xs:enumeration value="slot6"/>
+ <xs:enumeration value="misc2"/>
+ <xs:enumeration value="scarf"/>
+ <xs:enumeration value="scarfs"/>
+ <xs:enumeration value="slot7"/>
+ <xs:enumeration value="weapon"/>
+ <xs:enumeration value="weapons"/>
+ <xs:enumeration value="slot8"/>
+ <xs:enumeration value="shield"/>
+ <xs:enumeration value="shields"/>
+ <xs:enumeration value="slot9"/>
+ <xs:enumeration value="arrow"/>
+ <xs:enumeration value="arrows"/>
+ <xs:enumeration value="ammo"/>
+ <xs:enumeration value="slot10"/>
+ <xs:enumeration value="amulet"/>
+ <xs:enumeration value="amulets"/>
+ <xs:enumeration value="slot11"/>
+ <xs:enumeration value="ring"/>
+ <xs:enumeration value="rings"/>
+ <xs:enumeration value="slot12"/>
+ <xs:enumeration value="slot13"/>
+ <xs:enumeration value="slot14"/>
+ <xs:enumeration value="slot15"/>
+ <xs:enumeration value="slot16"/>
+ <xs:enumeration value="slot17"/>
+ <xs:enumeration value="slot18"/>
+ <xs:enumeration value="slot19"/>
+ <xs:enumeration value="slot20"/>
+ <xs:enumeration value="slot21"/>
+ <xs:enumeration value="slot22"/>
+ <xs:enumeration value="slot23"/>
+ <xs:enumeration value="slot24"/>
+ <xs:enumeration value="slot25"/>
+ <xs:enumeration value="slot26"/>
+ <xs:enumeration value=""/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!--
+ Units::loadXMLFile
+ unitsFile: units.xml
+ unitsPatchFile: units_patch.xml
+ unitsPatchDir: units.d/*.xml
+ -->
+ <xs:element name="units" type="root_units"/>
+ <xs:complexType name="root_units">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="unit">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="level">
+ <xs:complexType>
+ <xs:attribute name="symbol" type="xs:string" use="required"/>
+ <xs:attribute name="count" type="xs:int" use="required"/>
+ <xs:attribute name="round" type="xs:int" use="optional"/>
+ <xs:attribute name="separator" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="type" type="units_unit_type" use="required"/>
+ <xs:attribute name="conversion" type="xs:int" default="1"/>
+ <xs:attribute name="mix" type="yesno" default="no"/>
+ <xs:attribute name="base" type="xs:string" default="¤"/>
+ <xs:attribute name="round" type="xs:int" default="2"/>
+ <xs:attribute name="separator" type="xs:string" default=" "/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="currency">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="unit">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="level">
+ <xs:complexType>
+ <xs:attribute name="symbol" type="xs:string" use="required"/>
+ <xs:attribute name="count" type="xs:int" use="required"/>
+ <xs:attribute name="round" type="xs:int" use="optional"/>
+ <xs:attribute name="separator" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="conversion" type="xs:int" default="1"/>
+ <xs:attribute name="mix" type="yesno" default="no"/>
+ <xs:attribute name="base" type="xs:string" default="¤"/>
+ <xs:attribute name="round" type="xs:int" default="2"/>
+ <xs:attribute name="separator" type="xs:string" default=" "/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="units_unit_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="currency"/>
+ <xs:enumeration value="weight"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="yesno">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="true"/>
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!--
+ StatusEffect::loadXmlFile
+ statusEffectsFile: status-effects.xml
+ statusEffectsPatchFile: status-effects_patch.xml
+ statusEffectsPatchDir: status-effects.d/*.xml
+ -->
+ <xs:element name="status-effects" type="root_status-effects"/>
+ <xs:complexType name="root_status-effects">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="status-effect">
+ <xs:complexType>
+ <!-- legacy attribute only for old clients -->
+ <xs:attribute name="block-id" type="xs:int" use="optional"/>
+ <xs:attributeGroup ref="status_or_stun_attrs"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:attributeGroup name="status_or_stun_attrs">
+ <xs:attribute name="id" type="xs:int" use="optional"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="start-message" type="xs:string" use="optional"/>
+ <xs:attribute name="start-audio" type="xs:string" use="optional"/>
+ <xs:attribute name="start-particle" type="xs:string" use="optional"/>
+ <xs:attribute name="icon" type="xs:string" use="optional"/>
+ <xs:attribute name="action" type="xs:string" use="optional"/>
+ <xs:attribute name="persistent-particle-effect" type="yesno" use="optional"/>
+ <xs:attribute name="end-message" type="xs:string" use="optional"/>
+ <xs:attribute name="end-audio" type="xs:string" use="optional"/>
+ <xs:attribute name="end-particle" type="xs:string" use="optional"/>
+ <xs:attribute name="option" type="xs:int" use="optional"/>
+ <xs:attribute name="opt1" type="xs:int" use="optional"/>
+ <xs:attribute name="opt2" type="xs:int" use="optional"/>
+ <xs:attribute name="opt3" type="xs:int" use="optional"/>
+ </xs:attributeGroup>
+ <!--
+ maps and tilesets omitted, they have a DTD from tiled
+ -->
+ <!--
+ EmoteDB::loadXmlFile
+ emotesFile: emotes.xml
+ emotesPatchFile: emotes.xml
+ emotesPatchDir: emotes.d/*.xml
+ EmoteDB::loadSpecialXmlFile
+ manaplus_emotes.xml
+ -->
+ <xs:element name="emotes" type="root_emotes"/>
+ <xs:complexType name="root_emotes">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="emote">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="particlefx" type="xs:string"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <!-- altid is only in manaplus_emotes.xml -->
+ <xs:attribute name="altid" type="xs:int" use="optional"/>
+ <xs:attribute name="time" type="xs:int" default="500"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!--
+ NPCDB::loadXmlFile
+ npcsFile: npcs.xml
+ npcsPatchFile: npcs.xml
+ npcsPatchDir: npcs.d/*.xml
+ -->
+ <xs:element name="npcs" type="root_npcs"/>
+ <xs:complexType name="root_npcs">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="npc">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="particlefx" type="xs:string"/>
+ <xs:element name="menu">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="command" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="targetSelection" type="bool" default="true"/>
+ <xs:attributeGroup ref="being_basic_attributes"/>
+ <xs:attribute name="deadSortOffsetY" type="xs:int" default="31"/>
+ <xs:attribute name="avatar" type="xs:unsignedShort" default="0"/>
+ <xs:attribute name="allowDelete" type="bool" default="true"/>
+ <xs:attribute name="currency" type="xs:string" default=""/>
+ <xs:attribute name="allowEquipment" type="bool" default="false"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:attributeGroup name="being_basic_attributes">
+ <xs:attribute name="targetCursor" type="cursor" default="medium"/>
+ <!--
+ default for hoverCursor varies:
+ npc: "talk"
+ monster: "attack"
+ pet: "talk"
+ -->
+ <xs:attribute name="hoverCursor" type="xs:string" use="optional"/>
+ <xs:attribute name="targetOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="targetOffsetY" type="xs:int" default="0"/>
+ <xs:attribute name="nameOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="nameOffsetY" type="xs:int" default="0"/>
+ <xs:attribute name="sortOffsetY" type="xs:int" default="0"/>
+ <xs:attribute name="hpBarOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="hpBarOffsetY" type="xs:int" default="0"/>
+ <xs:attribute name="quickActionEffect" type="xs:int" default="-1"/>
+ <xs:attribute name="walkType" type="xs:string" default="walk"/>
+ </xs:attributeGroup>
+ <xs:simpleType name="cursor">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="small"/>
+ <xs:enumeration value="medium"/>
+ <xs:enumeration value="large"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!--
+ ItemDB::loadXmlFile
+ itemsFile: items.xml
+ itemsPatchFile: items_patch.xml
+ itemsPatchDir: items.d/*.xml
+ -->
+ <!-- not all item fields added -->
+ <xs:element name="items" type="root_items"/>
+ <xs:complexType name="root_items">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="item">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite" type="items_item_sprite"/>
+ <xs:element name="particlefx" type="xs:string"/>
+ <xs:element name="sound" type="items_item_sound"/>
+ <xs:element name="floor" type="items_item_floor"/>
+ <xs:element name="replace" type="items_item_replace"/>
+ <xs:element name="drawAfter" type="items_item_draworder"/>
+ <xs:element name="drawBefore" type="items_item_draworder"/>
+ <xs:element name="inventory" type="items_item_menu"/>
+ <xs:element name="storage" type="items_item_menu"/>
+ <xs:element name="cart" type="items_item_menu"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="type" type="items_item_type" default="other"/>
+ <xs:attribute name="weight" type="xs:int" default="0"/>
+ <xs:attribute name="view" type="xs:int" default="0"/>
+ <xs:attribute name="name" type="xs:string" default="unnamed"/>
+ <xs:attribute name="image" type="xs:string" use="optional"/>
+ <xs:attribute name="floor" type="xs:string" use="optional"/>
+ <xs:attribute name="description" type="xs:string" use="optional"/>
+ <xs:attribute name="attack-action" type="xs:string" use="optional"/>
+ <xs:attribute name="skyattack-action" type="xs:string" use="optional"/>
+ <xs:attribute name="waterattack-action" type="xs:string" use="optional"/>
+ <xs:attribute name="rideattack-action" type="xs:string" use="optional"/>
+ <xs:attribute name="drawBefore" type="xs:string" use="optional"/>
+ <xs:attribute name="drawAfter" type="xs:string" use="optional"/>
+ <xs:attribute name="maxFloorOffset" type="xs:int" default="0"/>
+ <xs:attribute name="useButton" type="xs:string" use="optional"/>
+ <xs:attribute name="useButton2" type="xs:string" use="optional"/>
+ <xs:attribute name="colors" type="xs:string" use="optional"/>
+ <xs:attribute name="iconColors" type="xs:string" use="optional"/>
+ <xs:attribute name="cardColor" type="xs:int" use="optional"/>
+ <!-- Can't use both tag and tag1; tag has precedence. -->
+ <xs:attribute name="tag" type="xs:string" use="optional"/>
+ <xs:attribute name="tag1" type="xs:string" use="optional"/>
+ <xs:attribute name="tag2" type="xs:string" use="optional"/>
+ <xs:attribute name="tag3" type="xs:string" use="optional"/>
+ <xs:attribute name="drawPriority" type="xs:int" default="0"/>
+ <xs:attribute name="attack-range" type="xs:int" default="0"/>
+ <xs:attribute name="missile-particle" type="xs:string" use="optional"/>
+ <xs:attribute name="missile-z" type="xs:float" use="optional"/>
+ <xs:attribute name="missile-lifetime" type="xs:int" use="optional"/>
+ <xs:attribute name="missile-speed" type="xs:float" use="optional"/>
+ <xs:attribute name="missile-diedistance" type="xs:float" use="optional"/>
+ <xs:attribute name="hit-effect-id" type="xs:string" use="optional"/>
+ <xs:attribute name="critical-hit-effect-id" type="xs:string" use="optional"/>
+ <xs:attribute name="miss-effect-id" type="xs:string" use="optional"/>
+ <xs:attribute name="sellProtected" type="bool" default="false"/>
+ <xs:attribute name="pickupCursor" type="xs:string" default="pickup"/>
+ <xs:attribute name="attack" type="xs:string" use="optional"/>
+ <xs:attribute name="criticalattack" type="xs:string" use="optional"/>
+ <xs:attribute name="criticalattackrate" type="xs:string" use="optional"/>
+ <xs:attribute name="atkspeed" type="xs:string" use="optional"/>
+ <xs:attribute name="mattack" type="xs:string" use="optional"/>
+ <xs:attribute name="block" type="xs:string" use="optional"/>
+ <xs:attribute name="defense" type="xs:string" use="optional"/>
+ <xs:attribute name="criticaldefense" type="xs:string" use="optional"/>
+ <xs:attribute name="mdefense" type="xs:string" use="optional"/>
+ <xs:attribute name="hp" type="xs:string" use="optional"/>
+ <xs:attribute name="mp" type="xs:string" use="optional"/>
+ <xs:attribute name="maxhp" type="xs:string" use="optional"/>
+ <xs:attribute name="maxmp" type="xs:string" use="optional"/>
+ <xs:attribute name="maxweight" type="xs:string" use="optional"/>
+ <xs:attribute name="hprecovery" type="xs:string" use="optional"/>
+ <xs:attribute name="sprecovery" type="xs:string" use="optional"/>
+ <xs:attribute name="money" type="xs:string" use="optional"/>
+ <xs:attribute name="exp" type="xs:string" use="optional"/>
+ <xs:attribute name="hit" type="xs:string" use="optional"/>
+ <xs:attribute name="level" type="xs:string" use="optional"/>
+ <xs:attribute name="speed" type="xs:string" use="optional"/>
+ <xs:attribute name="range" type="xs:string" use="optional"/>
+ <xs:attribute name="flee" type="xs:string" use="optional"/>
+ <xs:attribute name="str" type="xs:string" use="optional"/>
+ <xs:attribute name="agi" type="xs:string" use="optional"/>
+ <xs:attribute name="vit" type="xs:string" use="optional"/>
+ <xs:attribute name="int" type="xs:string" use="optional"/>
+ <xs:attribute name="dex" type="xs:string" use="optional"/>
+ <xs:attribute name="luk" type="xs:string" use="optional"/>
+ <xs:attribute name="effect" type="xs:string" use="optional"/>
+ <xs:attribute name="penalty" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="items_item_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="generic"/>
+ <xs:enumeration value="other"/>
+ <xs:enumeration value="usable"/>
+ <xs:enumeration value="equip-1hand"/>
+ <xs:enumeration value="equip-2hand"/>
+ <xs:enumeration value="equip-torso"/>
+ <xs:enumeration value="equip-arms"/>
+ <xs:enumeration value="equip-head"/>
+ <xs:enumeration value="equip-legs"/>
+ <xs:enumeration value="equip-shield"/>
+ <xs:enumeration value="equip-ring"/>
+ <xs:enumeration value="equip-charm"/>
+ <xs:enumeration value="equip-necklace"/>
+ <xs:enumeration value="equip-neck"/>
+ <xs:enumeration value="equip-feet"/>
+ <xs:enumeration value="equip-ammo"/>
+ <xs:enumeration value="card"/>
+ <xs:enumeration value="racesprite"/>
+ <xs:enumeration value="hairsprite"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="items_item_sprite">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ <xs:attribute name="race" type="xs:int" default="0"/>
+ <xs:attribute name="gender" default="unisex">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="unisex"/>
+ <xs:enumeration value="male"/>
+ <xs:enumeration value="female"/>
+ <xs:enumeration value="other"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="items_item_sound">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="event" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="hit"/>
+ <xs:enumeration value="strike"/>
+ <xs:enumeration value="miss"/>
+ <xs:enumeration value="use"/>
+ <xs:enumeration value="equip"/>
+ <xs:enumeration value="unequip"/>
+ <xs:enumeration value="drop"/>
+ <xs:enumeration value="pickup"/>
+ <xs:enumeration value="take"/>
+ <xs:enumeration value="put"/>
+ <xs:enumeration value="usecard"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="delay" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="items_item_floor">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="particlefx" type="xs:string"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="items_item_replace">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="item">
+ <xs:complexType>
+ <xs:attribute name="from" type="xs:int" use="optional"/>
+ <xs:attribute name="to" type="xs:int" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="sprite" type="items_item_x_sprite" use="optional"/>
+ <xs:attribute name="direction" type="items_item_x_direction" default="all"/>
+ </xs:complexType>
+ <xs:complexType name="items_item_draworder">
+ <xs:attribute name="name" type="items_item_x_sprite" use="required"/>
+ <xs:attribute name="priority" type="xs:int" use="optional"/>
+ <xs:attribute name="direction" type="items_item_x_direction" default="all"/>
+ </xs:complexType>
+ <xs:simpleType name="items_item_x_sprite">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="race"/>
+ <xs:enumeration value="type"/>
+ <xs:enumeration value="shoes"/>
+ <xs:enumeration value="boot"/>
+ <xs:enumeration value="boots"/>
+ <xs:enumeration value="bottomclothes"/>
+ <xs:enumeration value="bottom"/>
+ <xs:enumeration value="pants"/>
+ <xs:enumeration value="topclothes"/>
+ <xs:enumeration value="top"/>
+ <xs:enumeration value="torso"/>
+ <xs:enumeration value="body"/>
+ <xs:enumeration value="misc1"/>
+ <xs:enumeration value="misc2"/>
+ <xs:enumeration value="scarf"/>
+ <xs:enumeration value="scarfs"/>
+ <xs:enumeration value="hair"/>
+ <xs:enumeration value="hat"/>
+ <xs:enumeration value="hats"/>
+ <xs:enumeration value="wings"/>
+ <xs:enumeration value="glove"/>
+ <xs:enumeration value="gloves"/>
+ <xs:enumeration value="weapon"/>
+ <xs:enumeration value="weapons"/>
+ <xs:enumeration value="shield"/>
+ <xs:enumeration value="shields"/>
+ <xs:enumeration value="amulet"/>
+ <xs:enumeration value="amulets"/>
+ <xs:enumeration value="ring"/>
+ <xs:enumeration value="rings"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="items_item_x_direction">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="down"/>
+ <xs:enumeration value="downleft"/>
+ <xs:enumeration value="leftdown"/>
+ <xs:enumeration value="left"/>
+ <xs:enumeration value="upleft"/>
+ <xs:enumeration value="leftup"/>
+ <xs:enumeration value="up"/>
+ <xs:enumeration value="upright"/>
+ <xs:enumeration value="rightup"/>
+ <xs:enumeration value="right"/>
+ <xs:enumeration value="downright"/>
+ <xs:enumeration value="rightdown"/>
+ <xs:enumeration value="downall"/>
+ <xs:enumeration value="upall"/>
+ <xs:enumeration value="died"/>
+ <!-- handled by implicit else -->
+ <xs:enumeration value="all"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="items_item_menu">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="menu">
+ <xs:complexType>
+ <xs:attribute name="name1" type="xs:string" use="optional"/>
+ <xs:attribute name="name2" type="xs:string" use="optional"/>
+ <xs:attribute name="command1" type="xs:string" use="optional"/>
+ <xs:attribute name="command2" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ <!--
+ SoundDB::loadXmlFile
+ soundsFile: sounds.xml
+ soundsPatchFile: sounds_patch.xml
+ soundsPatchDir: sounds.d/*.xml
+ -->
+ <xs:element name="sounds" type="root_sounds"/>
+ <xs:complexType name="root_sounds">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="sound">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="languages" type="root_languages"/>
+ <xs:complexType name="root_languages">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="language">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="icon" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="texts" type="root_texts"/>
+ <xs:complexType name="root_texts">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="text">
+ <xs:complexType>
+ <xs:attribute name="show" type="bool" default="false"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="itemoptions" type="root_itemoptions"/>
+ <xs:complexType name="root_itemoptions">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="option">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="field" type="xs:string" use="optional"/>
+ <xs:attribute name="field0" type="xs:string" use="optional"/>
+ <xs:attribute name="field1" type="xs:string" use="optional"/>
+ <xs:attribute name="field2" type="xs:string" use="optional"/>
+ <xs:attribute name="field3" type="xs:string" use="optional"/>
+ <xs:attribute name="field4" type="xs:string" use="optional"/>
+ <xs:attribute name="field5" type="xs:string" use="optional"/>
+ <xs:attribute name="field6" type="xs:string" use="optional"/>
+ <xs:attribute name="field7" type="xs:string" use="optional"/>
+ <xs:attribute name="field8" type="xs:string" use="optional"/>
+ <xs:attribute name="field9" type="xs:string" use="optional"/>
+ <xs:attribute name="field10" type="xs:string" use="optional"/>
+ <xs:attribute name="field11" type="xs:string" use="optional"/>
+ <xs:attribute name="field12" type="xs:string" use="optional"/>
+ <xs:attribute name="field13" type="xs:string" use="optional"/>
+ <xs:attribute name="field14" type="xs:string" use="optional"/>
+ <xs:attribute name="field15" type="xs:string" use="optional"/>
+ <xs:attribute name="field16" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!--
+ ColorDB::loadHair
+ hairColorFile: hair.xml
+ hairColorPatchFile: hair.xml
+ hairColorPatchDir: hair.d/*.xml
+ ColorDB::loadColorLists
+ itemColorFile: itemcolors.xml
+ itemColorPatchFile: itemcolors_patch.xml
+ itemColorPatchDir: itemcolors.d/*.xml
+ -->
+ <xs:element name="colors" type="root_colors"/>
+ <xs:complexType name="root_colors">
+ <xs:sequence>
+ <xs:choice>
+ <!-- hair.xml -->
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="color" type="colors_color"/>
+ </xs:choice>
+ <!-- itemcolors.xml -->
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="list">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="color" type="colors_color"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="colors_color">
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ <!--
+ MapDB::loadInfo
+ mapsFile: maps.xml
+ mapsPatchFile: maps_patch.xml
+ mapsPatchDir: maps.d/*.xml
+ -->
+ <xs:element name="maps" type="root_maps"/>
+ <xs:complexType name="root_maps">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="map" type="maps_map"/>
+ <xs:element name="atlas" type="maps_atlas"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- MapDB::readMap -->
+ <xs:complexType name="maps_map">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="atlas">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ <!-- MapDB::readMap -->
+ <xs:complexType name="maps_atlas">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="file">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ <!--
+ MapDB::loadRemap
+ mapsRemapFile: maps/remap.xml
+ -->
+ <xs:element name="remap" type="root_remap"/>
+ <xs:complexType name="root_remap">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <!-- TODO <xs:element ref="include"/> -->
+ <xs:element name="map">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!--
+ DeadDB::loadXmlFile
+ deadMessagesFile: deadmessages.xml
+ deadMessagesPatchFile: deadmessages_patch.xml
+ deadMessagesPatchDir: deadmessages.d/*.xml
+ -->
+ <xs:element name="messages" type="root_messages"/>
+ <xs:complexType name="root_messages">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="message" type="xs:string"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!--
+ AvatarDB::loadXmlFile
+ avatarsFile: avatars.xml
+ avatarsPatchFile: avatars_patch.xml
+ avatarsPatchDir: avatars.d/*.xml
+ -->
+ <xs:element name="avatars" type="root_avatars"/>
+ <xs:complexType name="root_avatars">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="avatar">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="targetOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="targetOffsetY" type="xs:int" default="0"/>
+ <xs:attribute name="width" type="xs:int" default="0"/>
+ <xs:attribute name="height" type="xs:int" default="0"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!--
+ MonsterDB::loadXmlFile
+ monstersFile: monsters.xml
+ monstersPatchFile: monsters_patch.xml
+ monstersPatchDir: monsters.d/*.xml
+ -->
+ <xs:element name="monsters" type="root_monsters"/>
+ <xs:complexType name="root_monsters">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="monster">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sound">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="event" type="monster_sound_event" use="required"/>
+ <xs:attribute name="delay" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="attack">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="effect-id" type="xs:int" use="optional"/>
+ <xs:attribute name="hit-effect-id" type="xs:int" use="optional"/>
+ <xs:attribute name="critical-hit-effect-id" type="xs:int" use="optional"/>
+ <xs:attribute name="miss-effect-id" type="xs:int" use="optional"/>
+ <xs:attribute name="action" type="xs:string" default="attack"/>
+ <xs:attribute name="skyaction" type="xs:string" default="skyattack"/>
+ <xs:attribute name="wateraction" type="xs:string" default="waterattack"/>
+ <xs:attribute name="rideaction" type="xs:string" default="waterattack"/>
+ <xs:attribute name="missile-particle" type="xs:string" use="optional"/>
+ <xs:attribute name="missile-z" type="xs:float" use="optional"/>
+ <xs:attribute name="missile-lifetime" type="xs:int" use="optional"/>
+ <xs:attribute name="missile-speed" type="xs:float" use="optional"/>
+ <xs:attribute name="missile-diedistance" type="xs:float" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="particlefx" type="xs:string"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attributeGroup ref="being_basic_attributes"/>
+<!-- disable attributes for outdated servers
+ <xs:attribute name="maxHP" type="xs:int" use="optional"/> -->
+ <xs:attribute name="deadSortOffsetY" type="xs:int" default="31"/>
+ <xs:attribute name="colors" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ <!-- really optional with default="1002", but that's not sane -->
+ <xs:attribute name="offset" type="xs:int" default="1002"/>
+ </xs:complexType>
+ <xs:simpleType name="monster_sound_event">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="hit"/>
+ <xs:enumeration value="miss"/>
+ <xs:enumeration value="hurt"/>
+ <xs:enumeration value="die"/>
+ <xs:enumeration value="move"/>
+ <xs:enumeration value="sit"/>
+ <xs:enumeration value="sittop"/>
+ <xs:enumeration value="spawn"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!--
+ NpcDialogDB::load
+ -->
+ <xs:element name="dialogs" type="root_npc_dialogs"/>
+ <xs:complexType name="root_npc_dialogs">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="dialog" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="menu" type="npc_dialogs_menu"/>
+ <xs:element name="inventory" type="npc_dialogs_inventory"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="hideText" type="bool"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element ref="include"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="npc_dialogs_menu">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="button">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" default=""/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ <xs:attribute name="x" type="xs:int" default="0"/>
+ <xs:attribute name="y" type="xs:int" default="0"/>
+ <xs:attribute name="image" type="xs:string" default=""/>
+ <xs:attribute name="imageWidth" type="xs:int" default="16"/>
+ <xs:attribute name="imageHeight" type="xs:int" default="16"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="image">
+ <xs:complexType>
+ <xs:attribute name="image" type="xs:string" use="required"/>
+ <xs:attribute name="x" type="xs:int" default="0"/>
+ <xs:attribute name="y" type="xs:int" default="0"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="text">
+ <xs:complexType>
+ <xs:attribute name="text" type="xs:string" use="required"/>
+ <xs:attribute name="x" type="xs:int" default="0"/>
+ <xs:attribute name="y" type="xs:int" default="0"/>
+ <xs:attribute name="width" type="xs:int" default="20"/>
+ <xs:attribute name="height" type="xs:int" default="20"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="npc_dialogs_inventory">
+ <xs:attribute name="cell" type="xs:string" default=""/>
+ <xs:attribute name="columns" type="xs:int" default="10000"/>
+ </xs:complexType>
+
+ <!--
+ PETDB::loadXmlFile
+ petsFile: pets.xml
+ petsPatchFile: pets_patch.xml
+ petsPatchDir: pets.d/*.xml
+ -->
+ <xs:element name="pets" type="root_pets"/>
+ <xs:complexType name="root_pets">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="pet">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="particlefx" type="xs:string"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="targetSelection" type="bool" default="true"/>
+ <xs:attributeGroup ref="being_basic_attributes"/>
+ <xs:attribute name="deadSortOffsetY" type="xs:int" default="31"/>
+ <xs:attribute name="removeMessage" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="badges" type="root_badges"/>
+ <xs:complexType name="root_badges">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="guild" type="badges_list" />
+ <xs:element name="party" type="badges_list" />
+ <xs:element name="name" type="badges_list" />
+ <xs:element name="clan" type="badges_list" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="badges_list">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="badge">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="image" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="network" type="root_network"/>
+ <xs:complexType name="root_network">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="inpackets" type="network_inpackets" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="network_inpackets">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="fakepacket">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="len" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="removepacket">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="stats" type="root_stats"/>
+ <xs:complexType name="root_stats">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="basic">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="stat">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="optional"/>
+ <xs:attribute name="attr" type="xs:string" use="required"/>
+ <xs:attribute name="tag" type="xs:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="extended">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="stat">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="optional"/>
+ <xs:attribute name="attr" type="xs:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="page">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="stat">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="optional"/>
+ <xs:attribute name="attr" type="xs:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="horses" type="root_horses"/>
+ <xs:complexType name="horse_offset">
+ <xs:attribute name="direction" type="xs:string" use="required"/>
+ <xs:attribute name="horseOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="horseOffsetY" type="xs:int" default="0"/>
+ </xs:complexType>
+ <xs:complexType name="horse_sprite">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="root_horses">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="horse" type="horse_node" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="horse_node">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="offset">
+ <xs:complexType>
+ <xs:attribute name="direction" type="xs:string" use="required"/>
+ <xs:attribute name="riderOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="riderOffsetY" type="xs:int" default="0"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:element name="up" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite" type="horse_sprite" />
+ <xs:element name="offset" type="horse_offset" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="down" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite" type="horse_sprite" />
+ <xs:element name="offset" type="horse_offset" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:element name="itemfields" type="root_itemfields"/>
+ <xs:complexType name="root_itemfields">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:sequence>
+ <xs:element name="required" minOccurs="1" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="field" type="itemfield_node" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="add" minOccurs="1" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="field" type="itemfield_node" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="itemfield_node">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="description" type="xs:string" use="required"/>
+ <xs:attribute name="signed" type="bool" default="true"/>
+ </xs:complexType>
+
+ <xs:element name="equipmentslots" type="root_equipmentslots"/>
+ <xs:complexType name="root_equipmentslots">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="slot">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="slot" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="groups" type="root_groups"/>
+ <xs:complexType name="root_groups">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="group">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="commands" type="groups_commands" />
+ <xs:element name="permissions" type="groups_permissions" />
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" default=""/>
+ <xs:attribute name="longName" type="xs:string" default=""/>
+ <xs:attribute name="showBadge" type="bool" default="false"/>
+ <xs:attribute name="highlightName" type="bool" default="false"/>
+ <xs:attribute name="badge" type="xs:string" use="optional"/>
+ <xs:attribute name="inherit" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="groups_commands">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="command">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="use" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="groups_permissions">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="permission">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="enable" type="bool" default="true"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!-- probably not all tags correct here -->
+ <xs:element name="homunculuses" type="root_homunculuses"/>
+ <xs:complexType name="root_homunculuses">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="homunculus">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="particlefx" type="xs:string"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="targetSelection" type="bool" default="true"/>
+ <xs:attributeGroup ref="being_basic_attributes"/>
+ <xs:attribute name="deadSortOffsetY" type="xs:int" default="31"/>
+ <xs:attribute name="startFollowDistance" type="xs:int" default="3"/>
+ <xs:attribute name="followDistance" type="xs:int" default="0"/>
+ <xs:attribute name="warpDistance" type="xs:int" default="11"/>
+ <xs:attribute name="walkSpeed" type="xs:int" default="0"/>
+ <xs:attribute name="offsetX" type="xs:int" default="0"/>
+ <xs:attribute name="offsetY" type="xs:int" default="1"/>
+ <xs:attribute name="sitOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="sitOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="moveOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="moveOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="deadOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="deadOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="attackOffsetX" type="xs:int" use="optional"/>
+ <xs:attribute name="attackOffsetY" type="xs:int" use="optional"/>
+ <xs:attribute name="thinkTime" type="xs:int" default="500"/>
+ <xs:attribute name="directionType" type="xs:int" default="1"/>
+ <xs:attribute name="sitDirectionType" type="xs:int" default="1"/>
+ <xs:attribute name="deadDirectionType" type="xs:int" default="1"/>
+ <xs:attribute name="attackDirectionType" type="xs:int" default="4"/>
+ <xs:attribute name="removeMessage" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!-- probably not all tags correct here -->
+ <xs:element name="mercenaries" type="root_mercenaries"/>
+ <xs:complexType name="root_mercenaries">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="mercenary">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="particlefx" type="xs:string"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="targetSelection" type="bool" default="true"/>
+ <xs:attributeGroup ref="being_basic_attributes"/>
+ <xs:attribute name="deadSortOffsetY" type="xs:int" default="31"/>
+ <xs:attribute name="startFollowDistance" type="xs:int" default="3"/>
+ <xs:attribute name="followDistance" type="xs:int" default="0"/>
+ <xs:attribute name="warpDistance" type="xs:int" default="11"/>
+ <xs:attribute name="walkSpeed" type="xs:int" default="0"/>
+ <xs:attribute name="offsetX" type="xs:int" default="0"/>
+ <xs:attribute name="offsetY" type="xs:int" default="1"/>
+ <xs:attribute name="sitOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="sitOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="moveOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="moveOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="deadOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="deadOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="attackOffsetX" type="xs:int" use="optional"/>
+ <xs:attribute name="attackOffsetY" type="xs:int" use="optional"/>
+ <xs:attribute name="thinkTime" type="xs:int" default="500"/>
+ <xs:attribute name="directionType" type="xs:int" default="1"/>
+ <xs:attribute name="sitDirectionType" type="xs:int" default="1"/>
+ <xs:attribute name="deadDirectionType" type="xs:int" default="1"/>
+ <xs:attribute name="attackDirectionType" type="xs:int" default="4"/>
+ <xs:attribute name="removeMessage" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!-- probably not all tags correct here -->
+ <xs:element name="elementals" type="root_elementals"/>
+ <xs:complexType name="root_elementals">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="elemental">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="sprite">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="variant" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="particlefx" type="xs:string"/>
+ </xs:choice>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="targetSelection" type="bool" default="true"/>
+ <xs:attributeGroup ref="being_basic_attributes"/>
+ <xs:attribute name="deadSortOffsetY" type="xs:int" default="31"/>
+ <xs:attribute name="startFollowDistance" type="xs:int" default="3"/>
+ <xs:attribute name="followDistance" type="xs:int" default="0"/>
+ <xs:attribute name="warpDistance" type="xs:int" default="11"/>
+ <xs:attribute name="walkSpeed" type="xs:int" default="0"/>
+ <xs:attribute name="offsetX" type="xs:int" default="0"/>
+ <xs:attribute name="offsetY" type="xs:int" default="1"/>
+ <xs:attribute name="sitOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="sitOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="moveOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="moveOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="deadOffsetX" type="xs:int" default="0"/>
+ <xs:attribute name="deadOffsetY" type="xs:int" default="1"/>
+ <xs:attribute name="attackOffsetX" type="xs:int" use="optional"/>
+ <xs:attribute name="attackOffsetY" type="xs:int" use="optional"/>
+ <xs:attribute name="thinkTime" type="xs:int" default="500"/>
+ <xs:attribute name="directionType" type="xs:int" default="1"/>
+ <xs:attribute name="sitDirectionType" type="xs:int" default="1"/>
+ <xs:attribute name="deadDirectionType" type="xs:int" default="1"/>
+ <xs:attribute name="attackDirectionType" type="xs:int" default="4"/>
+ <xs:attribute name="removeMessage" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!-- not all item fields added -->
+ <xs:element name="clans" type="root_clans"/>
+ <xs:complexType name="root_clans">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="clan">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="maxhp" type="xs:string" use="optional"/>
+ <xs:attribute name="maxmp" type="xs:string" use="optional"/>
+ <xs:attribute name="str" type="xs:string" use="optional"/>
+ <xs:attribute name="agi" type="xs:string" use="optional"/>
+ <xs:attribute name="vit" type="xs:string" use="optional"/>
+ <xs:attribute name="int" type="xs:string" use="optional"/>
+ <xs:attribute name="dex" type="xs:string" use="optional"/>
+ <xs:attribute name="luck" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!--
+ ModDB::loadXmlFile
+ modsFile: mods.xml
+ modsPatchFile: mods_patch.xml
+ modsPatchDir: mods.d/*.xml
+ -->
+ <xs:element name="mods" type="root_mods"/>
+ <xs:complexType name="root_mods">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="include"/>
+ <xs:element name="mod">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="description" type="xs:string" use="optional"/>
+ <xs:attribute name="help" type="xs:string" use="optional"/>
+ <xs:attribute name="localdir" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!--
+ CharDB::load
+ charCreationFile: charcreation.xml
+ -->
+ <xs:element name="chars" type="root_chars"/>
+ <xs:complexType name="root_chars">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <!-- TODO <xs:element ref="include"/> -->
+ <xs:element name="haircolor">
+ <xs:complexType>
+ <xs:attribute name="min" type="xs:int" use="required"/>
+ <xs:attribute name="max" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hairstyle">
+ <xs:complexType>
+ <xs:attribute name="min" type="xs:int" use="required"/>
+ <xs:attribute name="max" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="look">
+ <xs:complexType>
+ <xs:attribute name="min" type="xs:int" use="required"/>
+ <xs:attribute name="max" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="stat">
+ <xs:complexType>
+ <xs:attribute name="min" type="xs:int" use="required"/>
+ <xs:attribute name="max" type="xs:int" use="required"/>
+ <xs:attribute name="sum" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="race">
+ <xs:complexType>
+ <xs:attribute name="min" type="xs:int" use="required"/>
+ <xs:attribute name="max" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="item">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <!--
+ SpriteDef::load
+ SpriteDef::loadSprite
+ -->
+ <xs:element name="sprite" type="root_sprite"/>
+ <xs:complexType name="root_sprite">
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <!-- SpriteDef::includeSprite -->
+ <xs:element name="include">
+ <xs:complexType>
+ <xs:attribute name="file" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- SpriteDef::loadImageSet -->
+ <xs:element name="imageset">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="width" type="xs:int" use="required"/>
+ <xs:attribute name="height" type="xs:int" use="required"/>
+ <xs:attribute name="src" type="xs:string" use="required"/>
+ <xs:attribute name="offsetX" type="xs:int" default="0"/>
+ <xs:attribute name="offsetY" type="xs:int" default="0"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- SpriteDef::loadAction -->
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <!-- SpriteDef::loadAnimation -->
+ <xs:element name="animation" type="animation_3"/>
+ </xs:choice>
+ <!-- TODO mostly enum? -->
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="imageset" type="xs:string" use="required"/>
+ <xs:attribute name="hp" type="xs:int" default="100"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="variants" type="xs:int" use="optional"/>
+ <xs:attribute name="variant_offset" type="xs:int" use="optional"/>
+ </xs:complexType>
+ <!--
+ WeaponsDB::load
+ weaponsFile: weapons.xml
+ weaponsPatchFile: weapons_patch.xml
+ weaponsPatchDir: weapons.d/*.xml
+ -->
+ <xs:element name="weapons" type="root_weapons"/>
+ <xs:complexType name="root_weapons">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="swords" type="weapons_items"/>
+ <xs:element name="bows" type="weapons_items"/>
+ <xs:element name="shields" type="weapons_items"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="weapons_items">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="item">
+ <xs:complexType>
+ <xs:attribute name="id" type="xs:integer" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+</xs:schema>
diff --git a/CI/testxml/xsd/xlink.xsd b/CI/testxml/xsd/xlink.xsd
new file mode 100644
index 0000000..2c53ec3
--- /dev/null
+++ b/CI/testxml/xsd/xlink.xsd
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>
+ <xs:attribute name="type">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="simple"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attributeGroup name="show">
+ <xs:attribute name="show" use="optional" form="qualified">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="embed"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="actuate">
+ <xs:attribute name="actuate" use="optional" form="qualified">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="onLoad"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="show1">
+ <xs:attribute name="show" use="optional" form="qualified">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="replace"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="actuate1">
+ <xs:attribute name="actuate" use="optional" form="qualified">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="onRequest"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="show2">
+ <xs:attribute name="show" use="optional" form="qualified">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="new"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-type">
+ <xs:attribute name="type" use="optional">
+ <xs:annotation>
+ <xs:documentation>Type of pointer to external rules files.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="simple">
+ <xs:annotation>
+ <xs:documentation>Simple link.</xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:attributeGroup>
+ <xs:attributeGroup name="its-href">
+ <xs:attribute name="href" type="xs:anyURI" use="optional">
+ <xs:annotation>
+ <xs:documentation>Pointer to external rules files.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+</xs:schema>
diff --git a/CI/testxml/xsd/xml.xsd b/CI/testxml/xsd/xml.xsd
new file mode 100644
index 0000000..aea7d0d
--- /dev/null
+++ b/CI/testxml/xsd/xml.xsd
@@ -0,0 +1,287 @@
+<?xml version='1.0'?>
+<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
+<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns ="http://www.w3.org/1999/xhtml"
+ xml:lang="en">
+
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+ <h1>About the XML namespace</h1>
+
+ <div class="bodytext">
+ <p>
+ This schema document describes the XML namespace, in a form
+ suitable for import by other schema documents.
+ </p>
+ <p>
+ See <a href="http://www.w3.org/XML/1998/namespace.html">
+ http://www.w3.org/XML/1998/namespace.html</a> and
+ <a href="http://www.w3.org/TR/REC-xml">
+ http://www.w3.org/TR/REC-xml</a> for information
+ about this namespace.
+ </p>
+ <p>
+ Note that local names in this namespace are intended to be
+ defined only by the World Wide Web Consortium or its subgroups.
+ The names currently defined in this namespace are listed below.
+ They should not be used with conflicting semantics by any Working
+ Group, specification, or document instance.
+ </p>
+ <p>
+ See further below in this document for more information about <a
+ href="#usage">how to refer to this schema document from your own
+ XSD schema documents</a> and about <a href="#nsversioning">the
+ namespace-versioning policy governing this schema document</a>.
+ </p>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:attribute name="lang">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>lang (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose value
+ is a language code for the natural language of the content of
+ any element; its value is inherited. This name is reserved
+ by virtue of its definition in the XML specification.</p>
+
+ </div>
+ <div>
+ <h4>Notes</h4>
+ <p>
+ Attempting to install the relevant ISO 2- and 3-letter
+ codes as the enumerated possible values is probably never
+ going to be a realistic possibility.
+ </p>
+ <p>
+ See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
+ http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
+ and the IANA language subtag registry at
+ <a href="http://www.iana.org/assignments/language-subtag-registry">
+ http://www.iana.org/assignments/language-subtag-registry</a>
+ for further information.
+ </p>
+ <p>
+ The union allows for the 'un-declaration' of xml:lang with
+ the empty string.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:union memberTypes="xs:language">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value=""/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="space">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>space (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose
+ value is a keyword indicating what whitespace processing
+ discipline is intended for the content of the element; its
+ value is inherited. This name is reserved by virtue of its
+ definition in the XML specification.</p>
+
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:NCName">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>base (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose value
+ provides a URI to be used as the base for interpreting any
+ relative URIs in the scope of the element on which it
+ appears; its value is inherited. This name is reserved
+ by virtue of its definition in the XML Base specification.</p>
+
+ <p>
+ See <a
+ href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
+ for information about this attribute.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <xs:attribute name="id" type="xs:ID">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>id (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose value
+ should be interpreted as if declared to be of type ID.
+ This name is reserved by virtue of its definition in the
+ xml:id specification.</p>
+
+ <p>
+ See <a
+ href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
+ for information about this attribute.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <xs:attributeGroup name="specialAttrs">
+ <xs:attribute ref="xml:base"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:attribute ref="xml:space"/>
+ <xs:attribute ref="xml:id"/>
+ </xs:attributeGroup>
+
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>Father (in any context at all)</h3>
+
+ <div class="bodytext">
+ <p>
+ denotes Jon Bosak, the chair of
+ the original XML Working Group. This name is reserved by
+ the following decision of the W3C XML Plenary and
+ XML Coordination groups:
+ </p>
+ <blockquote>
+ <p>
+ In appreciation for his vision, leadership and
+ dedication the W3C XML Plenary on this 10th day of
+ February, 2000, reserves for Jon Bosak in perpetuity
+ the XML name "xml:Father".
+ </p>
+ </blockquote>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+ <div xml:id="usage" id="usage">
+ <h2><a name="usage">About this schema document</a></h2>
+
+ <div class="bodytext">
+ <p>
+ This schema defines attributes and an attribute group suitable
+ for use by schemas wishing to allow <code>xml:base</code>,
+ <code>xml:lang</code>, <code>xml:space</code> or
+ <code>xml:id</code> attributes on elements they define.
+ </p>
+ <p>
+ To enable this, such a schema must import this schema for
+ the XML namespace, e.g. as follows:
+ </p>
+ <pre>
+ &lt;schema . . .>
+ . . .
+ &lt;import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ </pre>
+ <p>
+ or
+ </p>
+ <pre>
+ &lt;import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+ </pre>
+ <p>
+ Subsequently, qualified reference to any of the attributes or the
+ group defined below will have the desired effect, e.g.
+ </p>
+ <pre>
+ &lt;type . . .>
+ . . .
+ &lt;attributeGroup ref="xml:specialAttrs"/>
+ </pre>
+ <p>
+ will define a type which will schema-validate an instance element
+ with any of those attributes.
+ </p>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+ <div id="nsversioning" xml:id="nsversioning">
+ <h2><a name="nsversioning">Versioning policy for this schema document</a></h2>
+ <div class="bodytext">
+ <p>
+ In keeping with the XML Schema WG's standard versioning
+ policy, this schema document will persist at
+ <a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd</a>.
+ </p>
+ <p>
+ At the date of issue it can also be found at
+ <a href="http://www.w3.org/2001/xml.xsd">
+ http://www.w3.org/2001/xml.xsd</a>.
+ </p>
+ <p>
+ The schema document at that URI may however change in the future,
+ in order to remain compatible with the latest version of XML
+ Schema itself, or with the XML namespace itself. In other words,
+ if the XML Schema or XML namespaces change, the version of this
+ document at <a href="http://www.w3.org/2001/xml.xsd">
+ http://www.w3.org/2001/xml.xsd
+ </a>
+ will change accordingly; the version at
+ <a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd
+ </a>
+ will not change.
+ </p>
+ <p>
+ Previous dated (and unchanging) versions of this schema
+ document are at:
+ </p>
+ <ul>
+ <li><a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2007/08/xml.xsd">
+ http://www.w3.org/2007/08/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2004/10/xml.xsd">
+ http://www.w3.org/2004/10/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2001/03/xml.xsd">
+ http://www.w3.org/2001/03/xml.xsd</a></li>
+ </ul>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+</xs:schema>
+
diff --git a/CI/testxml/xsdcheck.sh b/CI/testxml/xsdcheck.sh
new file mode 100755
index 0000000..2052a2c
--- /dev/null
+++ b/CI/testxml/xsdcheck.sh
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+
+cd xsd
+DIR="$(pwd)/../../../client-data"
+rm ../errors.txt
+
+function check {
+ xmllint --format --schema tmw.xsd "${DIR}"/"${1}" 2>&1 >/dev/null | \
+ grep -v ": Skipping import of schema located at " | \
+ grep -v ".xml validates" | \
+ grep -v ".manaplus validates" >>../errors.txt
+}
+
+xmllint --format --schema XMLSchema.xsd tmw.xsd 2>&1 >/dev/null | \
+ grep -v ": Skipping import of schema located at " | \
+ grep -v ".xsd validates" >>../errors.txt
+
+check avatars.xml
+check badges.xml
+check charcreation.xml
+check deadmessages.xml
+check effects.xml
+check elementals.xml
+check emotes.xml
+check equipmentslots.xml
+check equipmentwindow.xml
+check tmw2.manaplus
+check features.xml
+check groups.xml
+check homunculuses.xml
+check horses.xml
+check itemcolors.xml
+check itemfields.xml
+check items.xml
+check maps.xml
+check mercenaries.xml
+check mods.xml
+check monsters.xml
+check npcdialogs.xml
+check npcs.xml
+check paths.xml
+check pets.xml
+check quests.xml
+check skills.xml
+check skillunits.xml
+check sounds.xml
+check stats.xml
+check status-effects.xml
+check units.xml
+check weapons.xml
+
+find -H "${DIR}/graphics" -type f -name "*.xml" -exec ./checkfile.sh {} \; >>../errors.txt
diff --git a/update/pseudo_update.sh b/update/pseudo_update.sh
new file mode 100755
index 0000000..9893b88
--- /dev/null
+++ b/update/pseudo_update.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2010-2012 TMW2 Online
+# Author: Andrei Karas (4144)
+
+dir=`pwd`
+
+previous=`cat commit.txt`
+rm upload/Extra.zip
+
+cd ../../client-data
+head=`git log --pretty=oneline -n 1 | awk '{print $1}'`
+u1=`echo ${previous} | cut -c 1-7`
+u2=`echo ${head} | cut -c 1-7`
+git diff --name-status ${previous} HEAD | awk '/^(A|M)\t/ {print $2}; /^(R...)\t/ {print $3}' | \
+grep -e "[.]\(xml\|png\|tmx\|ogg\|txt\|po\|tsx\|md\)" | sort | uniq | \
+xargs zip -X -9 -r ../tools/update/upload/Extra.zip
+
+cd $dir/upload
+
+sum=`adler32 Extra.zip | awk '{print $2}'`
+echo "Update ID: ${u1}..${u2}"
+echo "Checksum: ${sum}"
+
+echo "Extra.zip ${sum}" >>resources2.txt
+cp ../files/xml_header.txt resources.xml
+echo " <update type=\"data\" file=\"Extra.zip\" hash=\"${sum}\" />" >> resources.xml
+#cat ../files/xml_footer.txt >>resources.xml
+#cat ../files/xml_mods.txt >>resources.xml
+echo '</updates>' >>resources.xml
+
diff --git a/wiki/wikigen.py b/wiki/wikigen.py
new file mode 100755
index 0000000..7a7d2ec
--- /dev/null
+++ b/wiki/wikigen.py
@@ -0,0 +1,902 @@
+#! /usr/bin/env python3
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2010-2011 Evol Online
+# Copyright (C) 2018 TMW-2
+# Author: Andrei Karas (4144)
+# Author: Jesusalva
+
+import datetime
+import sys, traceback
+
+wikia=open("Items.md", "w")
+wikib=open("Monsters.md", "w")
+wikic=open("../../client-data/dyes.diff", "w") # Dye Report
+wikid=open("../../server-data/changechase.diff", "w") # ChangeChase Report
+
+# the TYPEs we use to determine where to pack things
+IT_HEALING=[]
+IT_ETC=[]
+IT_USABLE=[]
+IT_AMMO=[]
+IT_CARD=[]
+IT_PETEGG=[]
+IT_WEAPON={ 'HAND_2': [], # TWO HAND (LR)
+ 'HAND_1':[]} # WEAPONS (R)
+IT_ARMOR={ 'MISC': [], # FOR FAILURE
+ 'EQP_ACC_L': [], # ACCESSORY LEFT
+ 'EQP_ACC_R': [], # ACCESSORT RIGHT
+ 'EQP_HEAD_MID': [], # CHEST
+ 'EQP_SHOES': [], # FEET
+ 'EQP_GARMENT': [], # GLOVES
+ 'EQP_HEAD_LOW':[], # PANTS
+ '1024': [], # NECKLACES (should be EQP_COSTUME_HEAD_TOP instead of number)
+ '2048': [], # RINGS (should be EQP_COSTUME_HEAD_MID instead of number)
+ 'EQP_MOUNT':[], # MOUNTS (ie. EQP_SHADOW_SHOES)
+ 'EQP_HEAD_TOP':[], # HATS/HELMETS
+ 'EQP_HAND_L': []} # SHIELDS
+
+Mobs1=[]
+Mobs2=[]
+Mobs3=[]
+Mobs4=[]
+Mobs5=[]
+Mobs6=[]
+MobsA=[]
+
+SysDrops=[]
+
+
+def printSeparator():
+ print("--------------------------------------------------------------------------------")
+
+def showHeader():
+ print("TMW2 Wiki Generator")
+ ##print "Evol client data validator."
+ print("Run at: " + datetime.datetime.now().isoformat())
+ print("Usage: ./wikigen.py [<path_to_serverdata> <path_to_clientdata>]")
+ ##print "https://gitlab.com/evol/evol-tools/blob/master/testxml/testxml.py"
+ printSeparator()
+
+def showFooter():
+ #pass
+ #printSeparator()
+ print("Done.")
+
+
+
+
+
+
+class Mob:
+ def __init__(self):
+ # Basic
+ self.id="0"
+ #self.aegis="UnknownMonster" # SpriteName is not used anywhere, we are using its ID
+ self.name="Unknown Monster Name"
+ self.view="1"
+ self.chch=False
+ self.boss=False
+
+ # Defensive
+ self.mobpt="0" # Mob Points “Level”
+ self.hp="0"
+ self.xp="0"
+ self.jp="0"
+ self.st=""
+
+ # Offensive
+ self.atk="[0, 0]"
+ self.range="0"
+ self.move="0"
+ self.delay="0"
+ self.drops=[]
+
+def MobAlloc(ab):
+ try:
+ maab=int(ab.mobpt)
+ except:
+ maab=9901
+
+ if maab <= 20:
+ Mobs1.append(ab)
+ elif maab <= 40:
+ Mobs2.append(ab)
+ elif maab <= 60:
+ Mobs3.append(ab)
+ elif maab <= 80:
+ Mobs4.append(ab)
+ elif maab <= 100:
+ Mobs5.append(ab)
+ elif maab <= 150:
+ Mobs6.append(ab)
+ elif maab != 9901:
+ MobsA.append(ab)
+ else:
+ print("WARNING, Disregarding \"%s\" (ID: %s) as invalid mob" % (ab.name, ab.id))
+
+def testMobs():
+ print("\nGenerating Mob Wiki...")
+ if len(sys.argv) >= 2:
+ src=open(sys.argv[1]+"/db/pre-re/mob_db.conf", "r")
+ else:
+ src=open("../../server-data/db/pre-re/mob_db.conf", "r")
+
+ wikib.write("# Monster Database\n")
+ start=False
+ dropper=False
+ x=Mob() # Only for pyflakes2
+
+ for a in src:
+ if a == "{\n":
+ if start:
+ MobAlloc(x)
+ else:
+ start=True
+ x=Mob()
+
+ if " Id:" in a:
+ x.id=stp(a)
+ elif " Name:" in a:
+ x.name=stp(a)
+ elif " Hp:" in a:
+ x.hp=stp(a)
+ elif " Lv:" in a:
+ x.mobpt=stp(a)
+ elif " Exp:" in a:
+ x.xp=stp(a)
+ elif " JExp:" in a:
+ x.jp=stp(a)
+ elif " Attack:" in a:
+ x.atk=stp(a)
+ elif " AttackRange:" in a:
+ x.range=stp(a)
+ elif " MoveSpeed:" in a:
+ x.move=stp(a)
+ elif " ViewRange:" in a:
+ x.view=stp(a)
+ elif " AttackDelay:" in a:
+ x.delay=stp(a)
+ elif " Boss: true" in a:
+ x.boss=True
+ elif " Looter: true" in a:
+ x.st+="Lot,"
+ elif " Assist: true" in a:
+ x.st+="Ass,"
+ elif " Aggressive: true" in a:
+ x.st+="Agr,"
+ elif " ChangeChase: true" in a:
+ x.chch=True
+ elif 'Drops: ' in a:
+ dropper=True
+ elif dropper and '}' in a:
+ dropper=False
+ elif dropper:
+ x.drops.append(stp(a).split(": "))
+ # Write last entry
+ MobAlloc(x)
+
+ writeMob()
+
+ wikib.write('\n\n|Mode|Desc|\n|----|----|\n')
+ wikib.write('|Lot|Looter|\n')
+ wikib.write('|Ass|Assist|\n')
+ wikib.write('|Agr|Aggressive|\n')
+
+ src.close()
+
+def stp(x):
+ return x.replace('\n', '').replace('|', '').replace('(int, defaults to ', '').replace(')', '').replace('basic experience', '').replace('"','').replace(" ","").replace("\t","").replace('(string', '').replace('Name: ','').replace('AttackDelay: ', '').replace('MoveSpeed: ', '').replace('AttackRange: ', '').replace('ViewRange: ','').replace('Attack: ','').replace('ViewRange: ','').replace('Hp: ','').replace('Id: ','').replace('Lv: ','').replace('view range','').replace('attack range','').replace('move speed','').replace('health','').replace('(int','').replace('attack delay','atk.')
+
+
+def MonsterWrite(tbl):
+ # TODO: Check _mobs files to determine the usual monster density (a misc info to aid adding proper drop specs)
+ wikib.write("<table border=1>\n")
+ wikib.write("<tr><th>ID</th><th>Name</th><th>HP</th><th>Atk</th><th>Delay</th><th>Modes</th><th>Misc Info</th><th>Rewards</th><th>Drops</th></tr>\n")
+ for i in tbl:
+ if not i.chch:
+ wikid.write("%s:%s\n" % (i.id, i.name))
+ if i.boss:
+ i.name="<b>"+i.name+"</b>"
+ wikib.write('<tr><td><a name="' + i.id + '"></a>' +
+ i.id +"</td><td>"+
+ i.name +"</td><td>HP: "+
+ i.hp +"</td><td>Atk: "+
+ i.atk +"</td><td>"+
+ i.delay +" ms</td><td>"+
+ i.st +"</td><td>"+
+ mbdt('misc', mb_rdmisc(i)) +"</td><td>"+
+ mbdt('Exp\'s', mb_rdrw(i)) +"</td><td>"+
+ mbdt('drops', mb_rddrop(i)) +"</td></tr>\n"
+ )
+ wikib.write("</table>\n")
+ wikib.write("\n[(↑) Return to top](#monster-database)\n\n")
+
+def writeMob():
+ wikib.write("\
++ [Level 0-20](#starter)\n\
++ [Level 21-40](#apprentice)\n\
++ [Level 41-60](#intermediary)\n\
++ [Level 61-80](#advanced)\n\
++ [Level 81-100](#expert)\n\
++ [Level 101-150](#master)\n\
++ [Level 100+](#out-of-scope)\n\n\
+ ")
+
+ wikib.write("## Starter\n\n")
+ MonsterWrite(Mobs1)
+
+ wikib.write("## Apprentice\n\n")
+ MonsterWrite(Mobs2)
+
+ wikib.write("## Intermediary\n\n")
+ MonsterWrite(Mobs3)
+
+ wikib.write("## Advanced\n\n")
+ MonsterWrite(Mobs4)
+
+ wikib.write("## Expert\n\n")
+ MonsterWrite(Mobs5)
+
+ wikib.write("## Master\n\n")
+ MonsterWrite(Mobs6)
+
+ wikib.write("## Out Of Scope\n\n")
+ MonsterWrite(MobsA)
+
+
+def mbdt(summary, content):
+ return "<details>\
+<summary>"+summary+"</summary>\
+<pre>"+content+"</pre></details>"
+
+def mb_rdmisc(mb):
+ buff=""
+ if "agr" in mb.st.lower():
+ buff+="View Range: %s\n" % (mb.view)
+ buff+="Attack Range: %s\n" % (mb.range)
+ buff+="Move speed: %s ms\n" % (mb.move)
+ return buff
+
+def mb_rdrw(mb):
+ buff=""
+ buff+="MobPoints: %s\n" % (mb.mobpt)
+ buff+="%s\n" % (mb.xp)
+ buff+="%s\n" % (mb.jp)
+ return buff
+
+def mb_rddrop(mb):
+ buff=""
+ # sorted
+ try:
+ for ax in sorted(mb.drops, key=lambda xcv: float(xcv[1]), reverse=True):
+ # Ignore disabled drops
+ if ax[0].startswith("//"):
+ continue
+
+ # Write drop
+ try:
+ buff+=ax[0]+': ' + str(int(ax[1])/100.0) + ' %\n'
+ except IndexError:
+ print("Fatal: invalid %s mob with %s drops" % (mb.name, str(ax)))
+ exit(1)
+ except:
+ print("[Warning] %s incorrect drop: %s" % (mb.name, str(ax)))
+ buff+=ax[0]+': ' + ax[1] + ' ppm\n'
+
+ # Save to SysDrops
+ SysDrops.append([ax[0], ax[1], mb.name])
+ except:
+ traceback.print_exc()
+ print("Offender: %s" % mb.name)
+
+ return buff
+
+
+class It:
+ def __init__(self):
+ # Basic
+ self.id="0"
+ self.aegis="UnknownItem"
+ self.name="Unknown Item Name"
+ self.price="0" # Sell price, of course
+ self.weight="0"
+ self.type="IT_ETC" # default type
+ self.loc=""
+
+ # Offensive/Defensive
+ self.atk="0"
+ self.matk="0"
+ self.range="0"
+ self.defs="0"
+
+ # Restrictions (EquipLv)
+ self.lvl="0"
+ self.drop=True
+ self.trade=True
+ self.sell=True
+ self.store=True
+
+ # Special settings
+ self.rare=False # DropAnnounce
+ self.script=False
+
+ # Visual
+ self.sl="0" # Slots
+ self.ac=False # Allow Cards
+
+ # Script settings
+ self.minheal="0"
+ self.maxheal="0"
+ self.delheal="0"
+ self.typheal="0"
+ self.rarheal="0"
+
+def ItAlloc(it):
+ if (it.sl == "0" and it.ac) or (it.sl in ["1","2","3","4"] and not it.ac):
+ print("WARNING, item id "+it.id+" invalid dye/card setting!")
+ if (len(it.sl) > 1):
+ print("WARNING, item id "+it.id+" bad slots length: %d (%s)" % (len(it.sl), it.sl))
+ if it.ac:
+ wikic.write(it.id + ": " + it.name + "\n")
+
+ a=it.type
+ if "IT_HEALING" in a:
+ IT_HEALING.append(it)
+ elif "IT_ETC" in a:
+ IT_ETC.append(it)
+ elif "IT_USABLE" in a:
+ IT_USABLE.append(it)
+ elif "IT_AMMO" in a:
+ IT_AMMO.append(it)
+ elif "IT_CARD" in a:
+ IT_CARD.append(it)
+ elif "IT_PETEGG" in a:
+ IT_PETEGG.append(it)
+
+ elif "IT_WEAPON" in a:
+ if "HAND_L" in it.loc or "EQP_ARMS" in it.loc:
+ IT_WEAPON["HAND_2"].append(it)
+ elif "HAND_R" in it.loc:
+ IT_WEAPON["HAND_1"].append(it)
+ else:
+ raise Exception("Invalid location for weapon: %s" % it.loc)
+
+ elif "IT_ARMOR" in a:
+ if 'EQP_ACC_L' in it.loc:
+ IT_ARMOR['EQP_ACC_L'].append(it)
+ elif 'EQP_ACC_R' in it.loc:
+ IT_ARMOR['EQP_ACC_R'].append(it)
+ elif 'EQP_HEAD_MID' in it.loc:
+ IT_ARMOR['EQP_HEAD_MID'].append(it)
+ elif 'EQP_SHOES' in it.loc:
+ IT_ARMOR['EQP_SHOES'].append(it)
+ elif 'EQP_GARMENT' in it.loc:
+ IT_ARMOR['EQP_GARMENT'].append(it)
+ elif 'EQP_HEAD_LOW' in it.loc:
+ IT_ARMOR['EQP_HEAD_LOW'].append(it)
+ elif 'EQP_HEAD_TOP' in it.loc:
+ IT_ARMOR['EQP_HEAD_TOP'].append(it)
+ elif 'EQP_HAND_L' in it.loc:
+ IT_ARMOR['EQP_HAND_L'].append(it)
+ elif '1024' in it.loc:
+ IT_ARMOR['1024'].append(it)
+ elif '2048' in it.loc:
+ IT_ARMOR['2048'].append(it)
+ elif 'EQP_SHADOW_SHOES' in it.loc:
+ IT_ARMOR['EQP_MOUNT'].append(it)
+ elif 'EQP_ARMOR' in it.loc:
+ IT_ARMOR['EQP_ACC_R'].append(it) # Not really
+ else:
+ raise Exception("Invalid Loc for ID %s: %s" % (it.id, it.loc))
+
+def newItemDB():
+ print("\nGenerating Item Wiki...")
+ if len(sys.argv) >= 2:
+ src=open(sys.argv[1]+"/db/pre-re/item_db.conf", "r")
+ else:
+ src=open("../../server-data/db/pre-re/item_db.conf", "r")
+
+ x=It()
+ for a in src:
+ if a == "{\n":
+ ItAlloc(x)
+ x=It()
+
+ # sti() block
+ if " Id:" in a:
+ x.id=sti(a)
+ elif " AegisName:" in a:
+ x.aegis=sti(a)
+ elif " Name:" in a:
+ x.name=stin(a)
+ elif " Sell:" in a:
+ x.price=sti(a)
+ elif " Weight:" in a:
+ x.weight=sti(a)
+ elif " Type:" in a:
+ x.type=sti(a)
+ elif " Loc:" in a:
+ x.loc=sti(a)
+ elif " Atk:" in a:
+ x.atk=sti(a)
+ elif " Matk:" in a:
+ x.matk=sti(a)
+ elif " Range:" in a:
+ x.range=sti(a)
+ elif " Def:" in a:
+ x.defs=sti(a)
+ elif " EquipLv:" in a:
+ x.lvl=sti(a)
+ elif " Slots:" in a:
+ x.sl=sti(a)
+ elif " AllowCards:" in a:
+ x.ac=True
+ # Write booleans
+ elif "DropAnnounce: true" in a:
+ x.rare=True
+ elif "nodrop: true" in a:
+ x.drop=False
+ elif "notrade: true" in a:
+ x.trade=False
+ elif "noselltonpc: true" in a:
+ x.sell=False
+ elif "nostorage: true" in a:
+ x.store=False
+ elif "Script" in a:
+ x.script=True
+ # For healing items
+ elif "@min " in a:
+ x.minheal=sti(a)
+ elif "@max " in a:
+ x.maxheal=sti(a)
+ elif "@delay" in a:
+ x.delheal=sti(a)
+ elif "@type" in a:
+ x.typheal=sti(a)
+ try:
+ x.minheal=str(int(x.rarheal) * (int(x.typheal)*1 + 1)) + " %"
+ x.maxheal=str(int(x.rarheal) * (int(x.typheal)*2 + 1)) + " %"
+ if (x.delheal == "0"):
+ x.delheal=int(x.typheal)*2 + 1
+ except:
+ x.delheal="ERROR"
+ pass
+ elif "@rarity" in a:
+ x.rarheal=sti(a)
+ x.minheal=str(int(x.rarheal) * (int(x.typheal)*1 + 1)) + " %"
+ x.maxheal=str(int(x.rarheal) * (int(x.typheal)*2 + 1)) + " %"
+
+ # Write last entry
+ ItAlloc(x)
+ writeItems()
+
+ src.close()
+
+def sti(x):
+ return x.replace('\n', '').replace('|', '').replace(')', '').replace('Id: ', '').replace('"','').replace(" ","").replace("\t","").replace('AegisName: ', '').replace('Name: ','').replace('Sell: ', '').replace('Weight: ', '').replace('Type: ', '').replace('Loc: ', '').replace('Atk: ', '').replace('Matk: ', '').replace('Range: ', '').replace('Def: ', '').replace('EquipLv: ', '').replace('Slots: ','').replace(" ", "").replace('@min=','').replace('@max=','').replace('@delay=','').replace('@type=','').replace('@rarity=','').replace(';','')
+
+def stin(x):
+ return x.replace('\n', '').replace('|', '').replace(')', '').replace('Id: ', '').replace('"','').replace(" ","").replace("\t","").replace('Name: ','').replace(';','')
+
+
+def writeItems():
+ wikia.write("# Items\n\
++ [Healing Items](#healing-items)\n\
++ [Usable Items](#usable-items)\n\
++ [Generic Items](#generic-items)\n\
++ [Ammo](#ammo)\n\
++ [Cards](#cards)\n\
++ [Pet Eggs](#pet-eggs)\n\
++ [Mounts](#mounts)\n\
++ [Weapons](#weapons)\n\
+ + [1H Weapons](#1h-weapons)\n\
+ + [2H Weapons](#2h-weapons)\n\
++ [Armors](#armors)\n\
+ + [Left Accessory](#left-accessory)\n\
+ + [Right Accessory](#right-accessory)\n\
+ + [Headgear](#headgear)\n\
+ + [Chest](#chest)\n\
+ + [Pants](#pants)\n\
+ + [Shoes](#shoes)\n\
+ + [Necklaces](#necklaces)\n\
+ + [Rings](#rings)\n\
+ + [Gloves](#gloves)\n\
+ + [Shields](#shields)\n\
+\n\n")
+ wikia.write("#### Restrictions Reference\n")
+ wikia.write("Special Aegis Name Markers:\n\
++ * - Rare item with drop announce.\n\
++ (dp) - This item cannot be dropped.\n\
++ (tr) - This item cannot de traded.\n\
++ (sl) - This item cannot be sold.\n\
++ (gg) - This item cannot go to storage.\n\n")
+
+ # Healing Items
+ wikia.write("## Healing Items\n\n")
+ ItemWrite(IT_HEALING, ID=True, AEGIS=True, PRICE=True, WEIGHT=True, HEALING=True, DROPPER=True)
+
+ # Usable Items
+ wikia.write("## Usable Items\n")
+ ItemWrite(IT_USABLE, ID=True, AEGIS=True, NAME=True, PRICE=True, WEIGHT=True, DROPPER=True)
+
+ # Generic Items
+ wikia.write("## Generic Items\n")
+ ItemWrite(IT_ETC, ID=True, AEGIS=True, NAME=True, PRICE=True, WEIGHT=True, DROPPER=True)
+
+ # Ammo Items
+ wikia.write("## Ammo\n")
+ ItemWrite(IT_AMMO, ID=True, AEGIS=True, NAME=True, WEIGHT=True, ATK=True)
+
+ # Card Items
+ wikia.write("## Cards\n")
+ ItemWrite(IT_CARD, ID=True, AEGIS=True, NAME=True, PRICE=True, WEIGHT=True)
+
+ # Pet Egg Items
+ wikia.write("## Pet Eggs\n")
+ ItemWrite(IT_PETEGG, ID=True, AEGIS=True, NAME=True, WEIGHT=True)
+
+ # Mount Items
+ wikia.write("## Mounts\n")
+ ItemWrite(IT_ARMOR['EQP_MOUNT'], ID=True, AEGIS=True, NAME=True, WEIGHT=True)
+
+ ####################################################################
+ wikia.write("# Weapons\n")
+
+ # 1 Hand Items
+ wikia.write("## 1H Weapons\n")
+ ItemWrite(IT_WEAPON['HAND_1'], ID=True, AEGIS=True, PRICE=True, WEIGHT=True, ATK=True, LVL=True, DROPPER=True)
+
+ # 2 Hand Items
+ wikia.write("## 2H Weapons\n")
+ ItemWrite(IT_WEAPON['HAND_2'], ID=True, AEGIS=True, PRICE=True, WEIGHT=True, ATK=True, LVL=True, RANGE=True)
+
+
+ ####################################################################
+ wikia.write("# Armors\n")
+
+ ArmorWrite("Left Accessory",'EQP_ACC_L', False)
+ ArmorWrite("Right Accessory",'EQP_ACC_R', False)
+ ArmorWrite("Headgear",'EQP_HEAD_TOP')
+ ArmorWrite("Chest",'EQP_HEAD_MID')
+ ArmorWrite("Pants",'EQP_HEAD_LOW')
+ ArmorWrite("Shoes",'EQP_SHOES')
+ ArmorWrite("Necklaces",'1024', False)
+ ArmorWrite("Rings",'2048', False)
+ ArmorWrite("Gloves",'EQP_GARMENT')
+ ArmorWrite("Shields",'EQP_HAND_L')
+
+# Write AegisName with restrictions
+def hl(it):
+ buff=""
+ if it.rare:
+ buff+="*"
+ buff+=it.aegis
+ buff+=" "
+ if not it.drop:
+ buff+="<a href='#restrictions-reference'>(dp)</a>"
+ if not it.trade:
+ buff+="<a href='#restrictions-reference'>(tr)</a>"
+ if not it.sell:
+ buff+="<a href='#restrictions-reference'>(sl)</a>"
+ if not it.store:
+ buff+="<a href='#restrictions-reference'>(gg)</a>"
+ return buff
+
+# wikia.write("Id|Aegis|Name|Weight|Atk|Matk|\n")
+# wikia.write("Id|Aegis|Name|Price|Weight|\n")
+
+def ItemWrite(tbl, ID=False, AEGIS=False, NAME=False, PRICE=False, WEIGHT=False, DEF=False, LVL=False, ATK=False, RANGE=False, HEALING=False, SCRIPT=False, DROPPER=False):
+ wikia.write("<table border=1>\n")
+ wikia.write("<tr>")
+ if ID:
+ wikia.write("<th>ID</th>")
+ if AEGIS:
+ wikia.write("<th>Aegis</th>")
+ if NAME:
+ wikia.write("<th>Name</th>")
+ if PRICE:
+ wikia.write("<th>Price</th>")
+ if WEIGHT:
+ wikia.write("<th>Weight</th>")
+ if DEF:
+ wikia.write("<th>Def</th>")
+ if LVL:
+ wikia.write("<th>Lvl</th>")
+ if ATK:
+ wikia.write("<th>Atk</th>")
+ wikia.write("<th>Matk</th>")
+ if RANGE:
+ wikia.write("<th>Range</th>")
+ if HEALING:
+ wikia.write("<th>Min</th>")
+ wikia.write("<th>Max</th>")
+ wikia.write("<th>Delay</th>")
+ if SCRIPT:
+ wikia.write("<th>Script</th>")
+ if DROPPER:
+ wikia.write("<th>Mobs</th>")
+
+ wikia.write("</tr>\n")
+
+ for i in tbl:
+ """
+ # To sort by weight, for example, uncomment this block.
+ try:
+ zt=int(i.weight)
+ except:
+ tbl.remove(i)
+
+ for i in sorted(tbl, key=lambda xcv: int(xcv.weight), reverse=True):
+ """
+
+ wikia.write('<tr>')
+
+ if ID:
+ wikia.write("<td><a name=\"%s\"></a>%s</td>" % (i.id,i.id))
+ if AEGIS:
+ wikia.write("<td>%s</td>" % hl(i))
+ if NAME:
+ wikia.write("<td>%s</td>" % i.name)
+ if PRICE:
+ wikia.write("<td>%s GP</td>" % i.price)
+ if WEIGHT:
+ wikia.write("<td>%s g</td>" % i.weight)
+ if DEF:
+ wikia.write("<td>Def: %s</td>" % i.defs)
+ if LVL:
+ wikia.write("<td>Lv: %s</td>" % i.lvl)
+ if ATK:
+ wikia.write("<td>Atk: %s</td>" % i.atk)
+ wikia.write("<td>%s</td>" % i.matk)
+ if RANGE:
+ wikia.write("<td>%s</td>" % i.range)
+ if HEALING:
+ wikia.write("<td>%s</td>" % i.minheal)
+ wikia.write("<td>%s</td>" % i.maxheal)
+ wikia.write("<td>%s s</td>" % i.delheal)
+ if SCRIPT:
+ wikia.write("<td>%s</td>" % i.script)
+ # TODO: Check for item Aegis in npc/ folder too, to determine shops and quests.
+ if DROPPER:
+ tmp_droppers=""
+ tmp_drpalign=[]
+ for ax in SysDrops:
+ if ax[0] == i.aegis:
+ tmp_drpalign.append([ax[2], ax[1]])
+ if len(tmp_drpalign) > 0:
+ for a in sorted(tmp_drpalign, key=lambda xcv: float(xcv[1]), reverse=True):
+ try:
+ ppm=int(a[1])/100.0
+ tmp_droppers+=("%s: %.2f %% \n" % (a[0], ppm))
+ except:
+ print("[Warning] %s whodrop error: %s" % (i.name, str(a)))
+ wikia.write("<td>%s</td>" % mbdt("monsters", tmp_droppers))
+ else:
+ wikia.write("<td>-</td>")
+
+ wikia.write("</tr>")
+
+ wikia.write("</table>\n")
+ wikia.write("\n[(↑) Return to top](#items)\n\n")
+
+def ArmorWrite(name,scope,defitem=True):
+ wikia.write("## "+name+"\n")
+ ItemWrite(IT_ARMOR[scope], ID=True, AEGIS=True, PRICE=True, WEIGHT=True, DEF=defitem, LVL=True, DROPPER=True)
+
+
+
+
+
+
+
+
+
+
+
+class Quest:
+ def __init__(self, ide):
+ # Basic
+ self.id=ide
+ self.name="Unknown Quest Name"
+ self.group="Unknown"
+ self.ent=[]
+ self.level=0
+
+class QuestEntry:
+ def __init__(self):
+ # Basic
+ self.complete=False
+ self.entry=[] # collection of <text>
+ self.giver=""
+ self.reward=""
+ self.loc=""
+
+def sortlv(val):
+ return val[1]
+
+def qnt(string):
+ return string.replace(' ','').replace('"','').replace("'","").replace('<','').replace('>','').replace('nowiki=1', '').replace('nowiki', '')
+
+def qnt2(string):
+ return string.replace('##B','**').replace('##b','**').replace('##0','*').replace('##1','*').replace('##2','*').replace('##3','*').replace('##','*')
+
+def DoQuest():
+ print("\nGenerating Quest Wiki...")
+ if len(sys.argv) >= 3:
+ src=open(sys.argv[2]+"/quests.xml", "r")
+ else:
+ src=open("../../client-data/quests.xml", "r")
+
+ qlog=[]
+ q=Quest(-1)
+ qe=QuestEntry()
+ ig=False
+ nw=False
+
+ for e in src:
+ # Handle Comments and Ignored lines
+ if '<!--' in e and '-->' in e:
+ continue
+ elif '<!--' in e:
+ ig=True
+ elif '-->' in e:
+ ig=False
+ if '<effect' in e:
+ continue
+
+ if ig:
+ continue
+
+ # Handle Quest Headers
+ if '</var' in e:
+ if (nw):
+ nw=False
+ else:
+ qlog.append(q)
+ elif '<var' in e:
+ if 'nowiki' in e:
+ nw=True
+ g=qnt(e)
+ try:
+ q=Quest(int( g.replace('varid=','') ))
+ except:
+ print("Invalid quest: %s" % g)
+ exit(1)
+
+ # Handle quest entries
+ if '</quest>' in e:
+ q.ent.append(qe)
+ elif '<quest ' in e:
+ qe=QuestEntry()
+ l=e.split('"')
+ rc=[False, ""]
+ for arg in l:
+ if not rc[0]:
+ if "name" in arg:
+ rc=[True, 'name']
+ elif "group" in arg:
+ rc=[True, 'group']
+ elif "complete" in arg:
+ rc=[True, arg.replace('=','').replace(' ','')]
+ else:
+ if rc[1] == "name":
+ q.name=arg
+ elif rc[1] == "group":
+ q.group=arg
+ elif rc[1] == "complete":
+ qe.complete=True
+ elif rc[1] == "incomplete":
+ qe.complete=False
+ else:
+ print("Invalid <quest> tag: %s (arg was %s) (line was %s)" % (e, rc[1], l))
+ exit(1)
+ rc=[False, ""]
+
+ # Fill stuff in Quest Entry
+ if '<text' in e:
+ a=qnt2(e)
+ qe.entry.append( a.replace('<text>','').replace('</text>','').replace('<text ','<').replace("@@1", "text").replace("@@", "").strip() )
+ elif '<wiki' in e:
+ a=qnt2(e)
+ qe.entry.append( a.replace('<wiki>','').replace('</wiki>','').replace('<wiki ','<').replace("@@1", "text").replace("@@", "").strip() )
+ elif '<questgiver' in e:
+ a=qnt2(e)
+ qe.giver=a.replace('<questgiver>','').replace('</questgiver>','').strip()
+ elif '<reward' in e:
+ a=qnt2(e)
+ qe.reward=a.replace('<reward>','').replace('</reward>','').replace("@@", "text").replace('<reward ','<').strip()
+ elif '<coord' in e:
+ a=qnt2(e)
+ b=a.split('>')
+ qe.loc=b[1].replace('</coordinates','').strip()
+ elif '<level' in e:
+ a=qnt2(e)
+ qe.entry.append( "Required Level: " + a.replace('<level>','').replace('</level>','').strip() )
+ if (not q.level):
+ try:
+ q.level=int(a.replace('<level>','').replace('</level>','').strip())
+ except:
+ pass
+
+ # Done reading file
+ src.close()
+ aktbl={}
+ aksort=[]
+ print("\033[32;1mTotal quests: %d\033[0m" % len(qlog))
+ for i in qlog:
+ if i.name=="Unknown Quest Name":
+ print("Warning, invalid quest: %d" % (i.id))
+ qlog.remove(i)
+ continue
+ # Total Table
+ #print(str(i.id)+": "+i.name)
+ try:
+ if (i.level):
+ aktbl[i.group].append(("[%s](q/%d) (Lv %d)" % (i.name, i.id, i.level), i.level))
+ else:
+ aktbl[i.group].append(("[%s](q/%d)" % (i.name, i.id), i.level))
+ except:
+ if (i.level):
+ aktbl[i.group]=[("[%s](q/%d) (Lv %d)" % (i.name, i.id, i.level), i.level)]
+ else:
+ aktbl[i.group]=[("[%s](q/%d)" % (i.name, i.id), i.level)]
+ aksort.append(i.group)
+
+ for key in aktbl:
+ #print(aktbl[key]);
+ aktbl[key]=sorted(aktbl[key], key=sortlv)
+
+ # Individual file
+ f=open("../../wiki/q/"+str(i.id)+'.md', "w")
+ f.write("<!-- --- title: %d: %s -->\n\n" % (i.id, i.name))
+ f.write("# %s\n" % i.name)
+ f.write('\n')
+
+ totalcnt=0
+ for a in i.ent:
+ totalcnt+=1
+ f.write('\n### %d Stage\n\n' % totalcnt)
+ if a.complete:
+ f.write('*This completes quest*\n\n')
+
+ if a.giver != "" or a.reward != "" or a.loc != "":
+ f.write('```\n')
+ if a.giver != "":
+ f.write('Quest Giver: %s\n' % a.giver)
+ if a.reward != "":
+ f.write('Reward: %s\n' % a.reward.replace('@@', ''))
+ if a.loc != "":
+ f.write('Location: %s\n' % a.loc)
+ f.write('```\n\n')
+
+ for line in a.entry:
+ f.write('%s\n' % line)
+
+ f.write('\n\n****\nThis file is generated automatically. Editing it will have no effect.\n')
+ f.close()
+
+ # Write total table
+ f=open("Quests.txt", "w")
+ f.write("***Total quests: %d***\n" % len(qlog))
+ for key in aksort:
+ f.write('\n## %s\n\n' % key)
+ # TODO: Sort by Quest Level
+ for a in aktbl[key]:
+ f.write('+ '+a[0]+'\n')
+ f.close()
+
+showHeader()
+
+testMobs()
+newItemDB()
+DoQuest()
+
+wikia.close()
+wikib.close()
+wikic.close()
+wikid.close()
+#print(str(SysDrops))
+
+showFooter()
+exit(0)