diff --git a/PowerEditor/installer/APIs/perl.xml b/PowerEditor/installer/APIs/perl.xml
index d2571d0f5..1bc95b86d 100644
--- a/PowerEditor/installer/APIs/perl.xml
+++ b/PowerEditor/installer/APIs/perl.xml
@@ -255,7 +255,7 @@
-
+
diff --git a/appveyor.yml b/appveyor.yml
index 345bb4eee..60349197d 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -7,6 +7,7 @@ environment:
- platform: Win32
archi: x86
platform_input: Win32
+ PYTHON: "C:\\Python38"
- platform: x64
archi: amd64
@@ -34,7 +35,7 @@ build_script:
- if "%configuration%"=="Unicode Release" set scintilla_debug=
- if "%archi%" NEQ "" nmake SUPPORT_XP=1 %scintilla_debug% -f scintilla.mak
- if "%Platform%"=="mingw-w64_810_X64" mingw32-make -j%NUMBER_OF_PROCESSORS%
-
+
- cd "%APPVEYOR_BUILD_FOLDER%"\PowerEditor\visual.net\
- if "%archi%" NEQ "" msbuild notepadPlus.vcxproj /p:configuration="%configuration%" /p:platform="%platform_input%" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
- if "%Platform%"=="mingw-w64_810_X64" cd c:\projects\notepad-plus-plus\PowerEditor\gcc\ & mingw32-make -j%NUMBER_OF_PROCESSORS%
@@ -42,6 +43,11 @@ build_script:
after_build:
- cd "%APPVEYOR_BUILD_FOLDER%"
+ #xml files syntax checks
+ - if "%platform_input%"=="Win32" if "%configuration%"=="Unicode Debug" SET PATH=%PYTHON%;%PYTHON%\Scripts;%PATH%
+ - if "%platform_input%"=="Win32" if "%configuration%"=="Unicode Debug" python -m pip install requests rfc3987 pywin32 lxml
+ - if "%platform_input%"=="Win32" if "%configuration%"=="Unicode Debug" call python validator_xml.py
+
- ps: >-
$nppFileName = "Notepad++.$env:PLATFORM_INPUT.$env:CONFIGURATION.exe"
diff --git a/validator_xml.py b/validator_xml.py
new file mode 100644
index 000000000..1d6216701
--- /dev/null
+++ b/validator_xml.py
@@ -0,0 +1,114 @@
+#!/usr/local/bin/python3
+
+import os
+import io
+import sys
+
+import requests
+from hashlib import sha256
+from lxml import etree
+
+api_url = os.environ.get('APPVEYOR_API_URL')
+has_error = False
+
+
+def post_error(message):
+ global has_error
+
+ has_error = True
+
+ message = {
+ "message": message,
+ "category": "error",
+ "details": ""
+ }
+
+ if api_url:
+ requests.post(api_url + "api/build/messages", json=message)
+ else:
+ from pprint import pprint
+ pprint(message)
+
+
+def parse_xml_file(filename_xml):
+
+ # open and read schema file
+ #with open(filename_xsd, 'r') as schema_file:
+ #schema_to_check = schema_file.read()
+
+ # open and read xml file
+ #with open(filename_xml, 'r') as xml_file:
+ # xml_to_check = xml_file.read()
+
+ # parse xml
+ try:
+ doc = etree.parse(filename_xml)
+ #print(f'{filename_xml} XML well formed, syntax ok.')
+
+ # check for file IO error
+ except IOError:
+ #print('Invalid File')
+ post_error(f'{filename_xml}: IOError Invalid File')
+
+
+ # check for XML syntax errors
+ except etree.XMLSyntaxError as err:
+ #print('XML Syntax Error, see error_syntax.log')
+ post_error(f'{filename_xml}: {str(err.error_log)}: XMLSyntaxError Invalid File')
+
+ # check for general XML errors
+ except etree.LxmlError as err:
+ #print('XML Error, see error_syntax.log')
+ post_error(f'{filename_xml}: {str(err.error_log)}: LxmlError Invalid File')
+
+ except:
+ #print('Unknown error.')
+ post_error(f'{filename_xml}: Unknown error. Maybe check that no xml version is in the first line.')
+
+def parse_xml_files_from_APIs_dir():
+
+ for file in os.listdir("PowerEditor/installer/APIs"):
+ if file.endswith(".xml"):
+ #print(os.path.join("PowerEditor/installer/APIs", file))
+ parse_xml_file(os.path.join("PowerEditor/installer/APIs", file))
+
+def parse_xml_files_from_functionList_dir():
+
+ for file in os.listdir("PowerEditor/installer/functionList"):
+ if file.endswith(".xml"):
+ #print(os.path.join("PowerEditor/installer/functionList", file))
+ parse_xml_file(os.path.join("PowerEditor/installer/functionList", file))
+
+def parse_xml_files_from_nativeLang_dir():
+
+ for file in os.listdir("PowerEditor/installer/nativeLang"):
+ if file.endswith(".xml"):
+ #print(os.path.join("PowerEditor/installer/nativeLang", file))
+ parse_xml_file(os.path.join("PowerEditor/installer/nativeLang", file))
+
+def parse_xml_files_from_themes_dir():
+
+ for file in os.listdir("PowerEditor/installer/themes"):
+ if file.endswith(".xml"):
+ #print(os.path.join("PowerEditor/installer/themes", file))
+ parse_xml_file(os.path.join("PowerEditor/installer/themes", file))
+
+def parse_xml_files_from_src_dir():
+
+ for file in os.listdir("PowerEditor/src"):
+ if file.endswith(".xml"):
+ #print(os.path.join("PowerEditor/src", file))
+ parse_xml_file(os.path.join("PowerEditor/src", file))
+
+print('Start syntax check for xml files.')
+parse_xml_files_from_APIs_dir()
+parse_xml_files_from_functionList_dir()
+parse_xml_files_from_nativeLang_dir()
+parse_xml_files_from_themes_dir()
+parse_xml_files_from_src_dir()
+print('Done.')
+
+if has_error:
+ sys.exit(-2)
+else:
+ sys.exit()