Что нового

[RegExp] Получение SQL запроса из XML, XSD

IgRo

Знающий
Сообщения
65
Репутация
5
Из XML
Код:
<elem>
    <Ref>001</Ref>
    <IsFolder>True</IsFolder>
    <Description>Folder 1</Description>
    </Parent>
  </elem>
нужно получить строку запроса
Код:
INSERT INTO elem (Ref, IsFolder, Description,Parent)
VALUES ('001', 'True', 'Folder 1','');
 

ivsatel

Продвинутый
Сообщения
319
Репутация
84
Re: [RegExp] Получение имени и значение в XML

Может так подойдет?
Код:
#include <Array.au3>

Global $check = '0'
Dim $aName[1], $aNameTrue[1], $aValu[1], $aValuTrue[1]

$sNodeXML = "<elem>" & @CRLF & "  <Ref>001</Ref>" & @CRLF & "  <IsFolder>True</IsFolder>" & @CRLF _
& "  <Description>Folder 1</Description>" & @CRLF & "  </Parent>" & @CRLF & "</elem>" & @CRLF

For $i = 1 To 4

	$check += 1

If $check = '1' Then
	$sPattern = '\<(.*?)\>\d+'
EndIf
If $check = '2' Then
	$sPattern = '\<(.*?)\>True'
EndIf
If $check = '3' Then
	$sPattern = '\<(.*?)\>Folder'
EndIf
If $check = '4' Then
	$sPattern = '\s+\<\/(.*?)\>\r\n'
EndIf

	$aName = StringRegExp($sNodeXML, $sPattern, 3)

	_ArrayAdd($aNameTrue, $aName[0])

Next

$aNameClear = 'INSERT INTO table_name ('&$aNameTrue[1]&', '&$aNameTrue[2]&', '&$aNameTrue[3]&', '&$aNameTrue[4]&')'

$check = '0'

$sPattern = ''

For $i = 1 To 3

	$check += 1

If $check = '1' Then
	$sPattern = '\>(\d+)'
EndIf
If $check = '2' Then
	$sPattern = $aNameTrue[2]&'[\>](.*?)[\<]'
EndIf
If $check = '3' Then
	$sPattern = $aNameTrue[3]&'\>(.*?)\<\/'
EndIf

	$aValu = StringRegExp($sNodeXML, $sPattern, 3)

	_ArrayAdd($aValuTrue, $aValu[0])

Next

$aValuClear = 'VALUES ('&$aValuTrue[1]&', '&$aValuTrue[2]&', '&$aValuTrue[3]&', "")'

ConsoleWrite($aNameClear&@LF&$aValuClear&@LF)
 
Автор
I

IgRo

Знающий
Сообщения
65
Репутация
5
Re: [RegExp] Получение имени и значения Node из XML файла

ivsatel спасибо, но количество нодов (тегов) может быть разное и их очень много.

Интуиция мне подсказывает, что этот код не оптимальный, а требуется скорость обработки.
Код:
$sNodeXML= "<elem>" & @CRLF
$sNodeXML&= "  <Ref>001</Ref>" & @CRLF
$sNodeXML&= "  <IsFolder>True</IsFolder>" & @CRLF
$sNodeXML&= "  <Description>Folder 1</Description>" & @CRLF
$sNodeXML&= "  </Parent>" & @CRLF   ;!!!только закрытие т.к. значение NULL
$sNodeXML&= "</elem>" 
$sNodeXML =StringRegExpReplace($sNodeXML, '(?s)<[^\>]+>[\s\n\r]*(.*?)[\s\n\r]*</[^\>]+>\Z', '$1')
$sName =StringRegExpReplace($sNodeXML, '.*</(.*?)>.*', '$1')
$sName =StringRegExpReplace($sName, '(\n)', ',')
$sName="INSERT INTO table_name ("&$sName&')'
$sValue =StringRegExpReplace($sNodeXML, '.*>(.*?)</[^\>]+>.*', '$1')
$sValue =StringRegExpReplace($sValue, '(\n)', ',')
$sValue="VALUES ("&$sValue&')'
ConsoleWrite( $sName & @LF)
ConsoleWrite( $sValue & @LF)

Код:
INSERT INTO table_name (Ref,IsFolder,Description,Parent)
VALUES (001,True,Folder 1,  </Parent>)
</Parent> так и немогу победить :stars:
тоесть тег без открытия когда нет значения.
 

asdf8

Скриптер
Сообщения
564
Репутация
152
Re: [RegExp] Получение имени и значения Node из XML файла

IgRo [?]
</Parent> так и немогу победить
stars.gif
тоесть тег без открытия когда нет значения.

Может потому, что тег без значения общепринято отображать так :
Код:
<tag></tag>
или так:
Код:
<tag />

Можно попробовать следующий вариант :
Код:
#Include <Array.au3>

$sNodeXML = "<elem>" & @CRLF
$sNodeXML &= "  <Ref>001</Ref>" & @CRLF
$sNodeXML &= "  <IsFolder>True</IsFolder>" & @CRLF
$sNodeXML &= "  <Description>Folder 1</Description>" & @CRLF
$sNodeXML &= "  </Parent>" & @CRLF
$sNodeXML &= "</elem>"

$sNodeXML = StringRegExpReplace($sNodeXML, '(?im)[ \t]+</(\w+)>', '<\1></\1>')
$aData = StringRegExp($sNodeXML, '(?i)<(\w+)>([^<>]*)</\1>', 3)
If IsArray($aData) Then
	Dim $aOut[UBound($aData) / 2][2]
	For $i = 0 To UBound($aData) - 1 Step 2
		$aOut[$i / 2][0] = $aData[$i]
		$aOut[$i / 2][1] = $aData[$i + 1]
	Next
	_ArrayDisplay($aOut)
EndIf
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Re: [RegExp] Получение имени и значения Node из XML файла

IgRo,
Вариант?
Код:
;#include <Array.au3>

Local $sInsert = 'INSERT INTO table_name (', $sValue = 'VALUES (', $iUb
$sNodeXML = '<elem>' & @CRLF
$sNodeXML &= '	<Ref>001</Ref>' & @CRLF
$sNodeXML &= '	<IsFolder>True</IsFolder>' & @CRLF
$sNodeXML &= '	<Description>Folder 1</Description>' & @CRLF
$sNodeXML &= '	<Parent/>' & @CRLF;'	<Parent />'
$sNodeXML &= '</elem>'

$a_Tmp = StringRegExp($sNodeXML, '<([^<>/]+?)\h?/?>([^<>]+?)</', 3)
$iUb = UBound($a_Tmp)
If $iUb <> 8 Then Exit 13
;_ArrayDisplay($a_Tmp)
For $i = 0 To $iUb - 1 Step 2
    Switch $i
        Case 0 To 4
            $sInsert &= $a_Tmp[$i] & ', '
            $sValue &= $a_Tmp[$i + 1] & ', '
        Case Else
            $sValue &= '"")'
            $sInsert &= $a_Tmp[$i] & ')'
    EndSwitch
Next
ConsoleWrite($sInsert & @LF)
ConsoleWrite($sValue & @LF)
 
Автор
I

IgRo

Знающий
Сообщения
65
Репутация
5
Re: [RegExp] Получение имени и значения Node из XML файла

asdf8 спасибо Вы совершенно правы
должно быть именно tag(так) ;D
Код:
<tag />
соответственно
Код:
$sNodeXML = '<elem>' & @CRLF
$sNodeXML &= '  <Ref>001</Ref>' & @CRLF
$sNodeXML &= '  <IsFolder>True</IsFolder>' & @CRLF
$sNodeXML &= '  <Description>Folder 1</Description>' & @CRLF
$sNodeXML &= '  <Parent/>' & @CRLF ; !!!
$sNodeXML &= '</elem>'

madmasles, ivsatel спасибо буду тестить Ваши алгоритмы на скорость.
 
Автор
I

IgRo

Знающий
Сообщения
65
Репутация
5
Re: [RegExp] Получение имени и значения Node из XML файла

Код:
$sNodeXML = '<elem>' & @CRLF
$sNodeXML &= '  <Ref>001</Ref>' & @CRLF
$sNodeXML &= '  <IsFolder>True</IsFolder>' & @CRLF
$sNodeXML &= '  <Description>Folder 1</Description>' & @CRLF
$sNodeXML &= '  <Parent/>' & @CRLF ; !!!
$sNodeXML &= '</elem>'

$sTabName=StringRegExpReplace($sNodeXML, '(?s)<([^<>/]+)>.*</\1>', '$1')
$sNodeXML =StringRegExpReplace($sNodeXML, '(?s)<([^<>/]+)>\r?\n?(.*?)\r?\n?</\1>', '$2')
$sNodeXML = StringRegExpReplace($sNodeXML, '(?im)<([^<>/]+)/>', '<\1></\1>')
$sName =StringRegExpReplace($sNodeXML, '.*</([^<>/]+)>.*', '$1')
$sValue =StringRegExpReplace($sNodeXML, '.*<([^<>/]+)>(.*?)</\1>.*', "'$2'")
$sQuery="INSERT INTO "&$sTabName&"("&$sName&") " 
$sQuery&="VALUES("&$sValue&");"
$sQuery =StringRegExpReplace($sQuery, '(\n)', ', ')
ConsoleWrite( $sQuery & @CRLF)

Результат
Код:
INSERT INTO elem(Ref, IsFolder, Description, Parent) VALUES('001', 'True', 'Folder 1', '');


Добавлено:
Сообщение автоматически объединено:

Имеется XSD схема созданная по XML в первом посте
Код:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Root" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <xs:element name="Root" msdata:IsDataSet="true" msdata:Locale="en-US">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element name="Elem">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Ref" type="xs:string" minOccurs="0" />
              <xs:element name="IsFolder" type="xs:string" minOccurs="0" />
              <xs:element name="Description" type="xs:string" minOccurs="0" />
              <xs:element name="Parent" type="xs:string" minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>
На её основе требуется создать SQL запрос вида
Код:
CREATE TABLE Elem(Ref, IsFolder, Description, Parent);
 
Автор
I

IgRo

Знающий
Сообщения
65
Репутация
5
Код:
$sFileName="Tree.xsd"
$hFile = FileOpen($sFileName, 0)
$sXSD = FileRead($hFile)
FileClose($hFile)

;удаляем теги за исключением содержащих "xs:element name="
$sXSD=StringRegExpReplace($sXSD, '<(?!/?xs:element)[^<>]+>\r?\n?', '')
;удаляем теги содержащие "xs:element msdata"
$sXSD =StringRegExpReplace($sXSD, '\s*<xs:element.+msdata[^<>/]+>\r?\n?', '')
;удаляем слова
$sXSD=StringRegExpReplace($sXSD, '(form="unqualified")|(minOccurs="0")', '')
;удаляем пробелы в начале строки
$sXSD=StringRegExpReplace($sXSD, '(?s)(\s[^\n])+<', '<')
;таблица с именем
$sXSD=StringRegExpReplace($sXSD, '<xs:element name="(.*)"\s?>', 'CREATE TABLE $1(')
;имена полей
$sXSD=StringRegExpReplace($sXSD, '\r?\n?<xs:element name="', '')
$sXSD=StringRegExpReplace($sXSD, '"\s*type="xs:string"  />', ',')
;конец таблицы
$sXSD =StringRegExpReplace($sXSD, ',(\s*</xs:element>\s?)+', ');')
ConsoleWrite($sXSD& @CRLF)

OFFtop как скульптор отсекает все не нужное :smile:
 

xaker

Знающий
Сообщения
52
Репутация
16
вот еще вариант, в несколько раз быстрее.
Код:
#Include <Array.au3>

$test=StringRegExp(FileRead("Tree.xsd"), '<xs:element name="(.*)" type=', 3)
MsgBox(0, '', 'CREATE TABLE Elem(' & _ArrayToString( $test, ', ') & ');')
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
IgRo,
Код:
Opt('MustDeclareVars', 1)

Local $s_File = @ScriptDir & '\Tree.xsd', $i_Enc, $h_File, $s_Text, $a_Tmp, $i_Ub, $s_Query = 'CREATE TABLE '

$i_Enc = FileGetEncoding($s_File)
$h_File = FileOpen($s_File, $i_Enc)
$s_Text = FileRead($h_File)
FileClose($h_File)
$a_Tmp = StringRegExp($s_Text, 'name[^\w]*(?:''|")(\w+?)(?:''|")', 3)
$i_Ub = UBound($a_Tmp)
If $i_Ub <> 6 Then Exit 13
For $i = 1 To $i_Ub - 1
	Switch $i
		Case 1
			$s_Query &= $a_Tmp[$i] & '('
		Case 2 To 4
			$s_Query &= $a_Tmp[$i] & ', '
		Case 5
			$s_Query &= $a_Tmp[$i] & ');'
	EndSwitch
Next
ConsoleWrite($s_Query & @LF)
 

XpycT

Скриптер
Сообщения
380
Репутация
133
IgRo
Строка запроса из XML файла
Код:
Global $sXML = StringTrimRight(@ScriptFullPath, 4) & ".xml"

Global $oXML = ObjCreate("Msxml2.DOMDocument.6.0")

$oXML.Load($sXML)

$oNodes = $oXML.SelectNodes("root/elem")
If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oXML.SelectNodes | Error > " & $oXML.ParseError.Reason & @CR)

Dim $oChildNodes = $oNodes.Item(0).ChildNodes, $sFields = ""
For $iCN = 0 To $oChildNodes.Length
	$sFields &= $oChildNodes.Item($iCN).NodeName & ", "
Next
$sFields = StringTrimRight($sFields, 2)

For $oNode In $oNodes
	Dim $oChildNodes = $oNode.ChildNodes(), $sValues = ""

	For $iCN = 0 To $oChildNodes.Length
		$sValues &= "'" & $oChildNodes.Item($iCN).Text & "', "
	Next

	$sQuery = "INSERT INTO elem (" & $sFields & ") VALUES (" & StringTrimRight($sValues, 2) & ");"
	ConsoleWrite($sQuery& @CR)
Next


Строка запроса из XSD файла
Код:
Global $sXSD = StringTrimRight(@ScriptFullPath, 4) & ".xsd"

Global $oXML = ObjCreate("Msxml2.DOMDocument.6.0")

$oXML.Load($sXSD)

Dim $sNameSpaces = "", $oAttributes = $oXML.ChildNodes.Item(1).Attributes
For $a = 2 To $oAttributes.Length
	$sNameSpaces &= $oAttributes.Item($a).NodeName & '="' & $oAttributes.Item($a).Text & '" '
Next
$sNameSpaces = StringTrimRight($sNameSpaces, 1)

$oXML.SetProperty ("SelectionNamespaces", $sNameSpaces)

$oNode = $oXML.SelectSingleNode("xs:schema/xs:element/xs:complexType/xs:choice/xs:element")
If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oXML.SelectSingleNode | Error > " & $oXML.ParseError.Reason & @CR)

$sTableName = $oNode.GetAttribute("name")

$oNodes = $oXML.SelectNodes("xs:schema/xs:element/xs:complexType/xs:choice/xs:element/xs:complexType/xs:sequence/xs:element")
If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oXML.SelectNodes | Error > " & $oXML.ParseError.Reason & @CR)

$sFields = ""
For $oNode In $oNodes
	$sName = $oNode.GetAttribute("name")
	$sType = $oNode.GetAttribute("type")

	$sFields &= $sName & ", "
Next
$sFields = StringTrimRight($sFields, 2)

$sQuery = "CREATE TABLE " & $sTableName & " (" & $sFields & ");"
ConsoleWrite($sQuery& @CR)
 
Автор
I

IgRo

Знающий
Сообщения
65
Репутация
5
Спасибо xaker, madmasles, XpycT
OFF Я уже думал, что придумал. Ан нет. Возможны варианты :scratch:
Вложил рабочий XSD для тестов кода
Он содержит несколько таблиц с разными полями

xaker
краткость сестра таланта
:smile:
madmasles
Код:
'name[^\w]*(?:''|")(\w+?)(?:''|")'
странно не включает русские имена. Для \w русские слова не слова?
XpycT
Тест скорости обработки XML:
RegExp = 1.18 s.
XMLDOM=25.31 s.
Код:
Dim $sFileXML = StringTrimRight(@ScriptFullPath, 4) & ".xml"

_GenXML($sFileXML)
$sXML = _ReadXML($sFileXML)
_GetInsertQuery_RegExp($sXML)
_GetInsertQuery_XMLDOM($sXML)

Func _ReadXML($sFileXML)
   Local $iEnc, $hFileXML, $sXML
   $iEnc = FileGetEncoding($sFileXML)
   $hFileXML = FileOpen($sFileXML, $iEnc)
   $sXML = FileRead($hFileXML)
   FileClose($hFileXML)
   Return $sXML
EndFunc
Func _GetInsertQuery_RegExp($sNodeXML)
	ConsoleWrite("=====RegExp===" & @CRLF)
	Local $Timer = TimerInit()
	$sTabName = StringRegExpReplace($sNodeXML, '(?s)<([^<>/]+)>.*</\1>', '$1')
	$sNodeXML = StringRegExpReplace($sNodeXML, '(?s)<([^<>/]+)>\r?\n?(.*?)\r?\n?</\1>', '$2')
	$sNodeXML = StringRegExpReplace($sNodeXML, '(?im)<([^<>/]+)/>', '<\1></\1>')
	$sName = StringRegExpReplace($sNodeXML, '.*</([^<>/]+)>.*', '$1')
	$sValue = StringRegExpReplace($sNodeXML, '.*<([^<>/]+)>(.*?)</\1>.*', "'$2'")
	$sQuery = "INSERT INTO " & $sTabName & "(" & $sName & ") "
	$sQuery &= "VALUES(" & $sValue & ");"
	$sQuery = StringRegExpReplace($sQuery, '(\n)', ', ')
	;ConsoleWrite( $sQuery & @CRLF)
	ConsoleWrite('Time  RegExp ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)
 EndFunc
Func _GetInsertQuery_XMLDOM($sNodeXML)
	ConsoleWrite("===XMLDOM=====" & @CRLF)
	;Local $Timer = TimerInit()
	Local $oXML = ObjCreate('Microsoft.XMLDOM')
	If Not IsObj($oXML) Then
		MsgBox(16, 'Ошибка', 'MsXML не установлен.')
		Exit 1
	EndIf
	$ok = $oXML.LoadXML($sNodeXML)
	If Not $ok Then
		;MsgBox(16, 'Ошибка', 'Файл '&$FileXML&' не прочитан.')
		With $oXML.parseError
			If .errorCode <> 0 Then
				MsgBox(16, 'Ошибка', 'В файле ' & $FileXML & @CRLF & _
						'Код ошибки: ' & .errorCode & @CRLF & _
						'Номер строки с ошибкой: ' & .line & @CRLF & _
						'Позиция ошибки в строке: ' & .linePos & @CRLF & _
						'Позиция ошибки в файле: ' & .filePos & @CRLF & _
						'Причина ошибки: ' & .reason)
				Exit 3
			EndIf
		EndWith
		Exit 2
	EndIf
	$oNodes = $oXML.SelectNodes("Root/Elem")
	If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oXML.SelectNodes | Error > " & $oXML.ParseError.Reason & @CR)
	Dim $sFields = ""
	Dim $oChildNodes = $oNodes.Item(0).ChildNodes
	For $iCN = 0 To $oChildNodes.Length -1 ;!!!
		$sFields &= $oChildNodes.Item($iCN).NodeName & ", "
	Next
	$sFields = StringTrimRight($sFields, 2)
	Local $Timer = TimerInit()
	For $oNode In $oNodes
		Dim $oChildNodes = $oNode.ChildNodes(), $sValues = ""
		For $iCN = 0 To $oChildNodes.Length -1 ;!!!
			$sValues &= "'" & $oChildNodes.Item($iCN).Text & "', "
		Next
		$sQuery = "INSERT INTO elem (" & $sFields & ") VALUES (" & StringTrimRight($sValues, 2) & ");"
		;ConsoleWrite($sQuery& @CR)
	Next
	ConsoleWrite('Time XMLDOM ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)
EndFunc


 
 Func _GenXML($sFileXML)
	;Local $sFileXML = FileOpenDialog("Указать файл", @WorkingDir & "", "XML (*.XML)", 1 + 4, "Tree.XML")
	;If @error Then Return
	;Local $sFileXML = 'Tree.XML'
	$FileXML = FileOpen($sFileXML, 2)
	FileWrite($FileXML, "<Root>" & @CRLF)
	For $X1 = 1 To 10
		$Ref1 = _WinAPI_CreateGUID()
		FileWrite($FileXML, "<Elem>" & @CRLF)
		FileWrite($FileXML, "<Ref>" & $Ref1 & "</Ref>" & @CRLF)
		FileWrite($FileXML, "<IsFolder>True</IsFolder>" & @CRLF)
		FileWrite($FileXML, "<Description>Folder 0_" & $X1 & "</Description>" & @CRLF)
		FileWrite($FileXML, "<Parent>00000000-0000-0000-0000-000000000000</Parent>" & @CRLF)
		FileWrite($FileXML, "</Elem>" & @CRLF)
		For $X2 = 1 To 30
			$Ref2 = _WinAPI_CreateGUID()
			FileWrite($FileXML, "<Elem>" & @CRLF)
			FileWrite($FileXML, "<Ref>" & $Ref2 & "</Ref>" & @CRLF)
			FileWrite($FileXML, "<IsFolder>True</IsFolder>" & @CRLF)
			FileWrite($FileXML, "<Description>Folder " & $X1 & "_" & $X1 & "</Description>" & @CRLF)
			FileWrite($FileXML, "<Parent>" & $Ref1 & "</Parent>" & @CRLF)
			FileWrite($FileXML, "</Elem>" & @CRLF)
			For $X3 = 1 To 100;0
				$Ref3 = _WinAPI_CreateGUID()
				FileWrite($FileXML, "<Elem>" & @CRLF)
				FileWrite($FileXML, "<Ref>" & $Ref3 & "</Ref>" & @CRLF)
				FileWrite($FileXML, "<IsFolder>False</IsFolder>" & @CRLF)
				FileWrite($FileXML, "<Description>Elem " & $X2 & "_" & $X3 & "</Description>" & @CRLF)
				FileWrite($FileXML, "<Parent>" & $Ref2 & "</Parent>" & @CRLF)
				FileWrite($FileXML, "</Elem>" & @CRLF)
			Next
		Next
	Next
	FileWrite($FileXML, "</Root>" & @CRLF)
	FileClose($FileXML)
EndFunc   ;==>_GenXML
Func _WinAPI_CreateGUID()
	Local Const $tagGUID = "int Data1;short Data2;short Data3;byte Data4[8]"
	Local $tData = DllStructCreate('wchar[39]')
	Local $tGUID = DllStructCreate($tagGUID)
	Local $Return
	$Return = DllCall('ole32.dll', 'uint', 'CoCreateGuid', 'ptr', DllStructGetPtr($tGUID))
	If @error Then Return SetError(1, 1, 0)
	If $Return[0] Then Return SetError(1, $Return[0], 0)
	$Return = DllCall('ole32.dll', 'int', 'StringFromGUID2', 'ptr', DllStructGetPtr($tGUID), 'ptr', DllStructGetPtr($tData), 'int', 39)
	If(@error) Or(Not $Return[0]) Then Return SetError(1, 1, 0)
	;Return DllStructGetData($tData, 1)
	Return StringMid( DllStructGetData($tData, 1), 2, 36)
EndFunc   ;==>_WinAPI_CreateGUID
 

xaker

Знающий
Сообщения
52
Репутация
16
Код:
#Include <Array.au3>

$test=StringRegExp(FileRead("2.xsd"), '(?s)                  <xs:sequence>(.*?)</xs:sequence>', 3)

For $i = 0 To UBound($test) - 1
	$test[$i] = StringRegExp( $test[$i], '<xs:element name="(.*?)"', 3)
	$test[$i] = 'CREATE TABLE Elem(' & _ArrayToString( $test[$i], ', ') & ');'
Next

_ArrayDisplay($test)
 
Автор
I

IgRo

Знающий
Сообщения
65
Репутация
5
xaker :beer: только имен таблиц нет
Должно быть
Код:
CREATE TABLE CatalogObject.ВидыНоменклатуры (Ref, IsFolder,  ..);
CREATE TABLE CatalogObject.КлассификаторЕдиницИзмерения (Ref, ...);
CREATE TABLE CatalogObject.ЕдиницыИзмерения (Ref, DeletionMark, ...);
CREATE TABLE CatalogObject.СтатьиЗатрат (Ref, IsFolder,....);
CREATE TABLE CatalogObject.Номенклатура (Ref, IsFolder, DeletionMark, ...);
 

xaker

Знающий
Сообщения
52
Репутация
16
сорри
Код:
#Include <Array.au3>

$sFile = FileRead("2.xsd")
$test=StringRegExp($sFile, '(?s)                  <xs:sequence>(.*?)</xs:sequence>', 3)
$test2 = StringRegExp($sFile, '<xs:element name="(.*?)" form="unqualified">\R                <xs:complexType>', 3)
For $i = 0 To UBound($test) - 1
	$test[$i] = StringRegExp( $test[$i], '<xs:element name="(.*?)"', 3)
	$test[$i] = 'CREATE TABLE ' & $test2[$i] & ' (' & _ArrayToString( $test[$i], ', ') & ');'
Next

_ArrayDisplay($test)
 
Автор
I

IgRo

Знающий
Сообщения
65
Репутация
5
xaker почти в 5 раз быстрее
Код:
#include <array.au3>

Dim $s_File = "2.xsd"
Dim $i_Enc, $h_File, $s_Text
$i_Enc = FileGetEncoding($s_File)
$h_File = FileOpen($s_File, $i_Enc)
$sXSD = FileRead($h_File)
FileClose($h_File)

$oXML = ObjCreate('Microsoft.XMLDOM')

_GetTableQuery_xaker($sXSD)
_GetTableQuery_XpycT($sXSD)
_GetTableQuery_IgRo($sXSD)



Func _GetTableQuery_xaker($sXSD)
 ConsoleWrite("===xaker=====" & @CRLF)	
Local $Timer = TimerInit()
   $test=StringRegExp($sXSD, '(?s)<xs:sequence>(.*?)</xs:sequence>', 3)
   $test2 = StringRegExp($sXSD, '<xs:element name="(.*?)"\s*form="unqualified">\R\s*<xs:complexType>', 3)
   For $i = 0 To UBound($test) - 1
	   $test[$i] = StringRegExp( $test[$i], '<xs:element name="(.*?)"', 3)
	   $test[$i] = 'CREATE TABLE ' & $test2[$i] & ' (' & _ArrayToString( $test[$i], ', ') & ');'
   Next
   $sQuery=_ArrayToString( $test, ';'&@CRLF)
   ;ConsoleWrite($sQuery & @CRLF)
   ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)
EndFunc


Func _GetTableQuery_XpycT($sXSD)
    ConsoleWrite("===XpycT=====" & @CRLF)
    Local $Timer = TimerInit()
	
	$oXML.LoadXML($sXSD)
	$XPath = "xs:schema"
	$XPath &= "/xs:element"
	$XPath &= "/xs:complexType"
	$XPath &= "/xs:choice"
	$XPath &= "/xs:element" ;Data
	$XPath &= "/xs:complexType"
	$XPath &= "/xs:sequence"
	$XPath &= "/xs:element" ;Таблицы
	$oTableNodes = $oXML.SelectNodes($XPath)
	If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oTableNodes | Error > " & $oXML.ParseError.Reason & @CR)
	For $iTable = 0 To $oTableNodes.Length -1
		$sTableName = $oTableNodes.Item($iTable).GetAttribute("name")
		; 1 вариант
;~ 		$XPath &= "[" & $iTable & "]/xs:complexType"
;~ 		$XPath &= "/xs:sequence"
;~ 		$XPath &= "/xs:element"
;~ 		$oFieldNodes = $oXML.SelectNodes($XPath)
;~ 		If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oFieldNodes v1 | Error > " & $oXML.ParseError.Reason & @CR)
		; 2 вариант
		$oFieldNodes = $oTableNodes.Item($iTable).ChildNodes().Item(0).ChildNodes().Item(0).ChildNodes()
		If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oFieldNodes v2 | Error > " & $oXML.ParseError.Reason & @CR)
		$sFields = ""
		For $oFieldNode In $oFieldNodes
			$sName = $oFieldNode.GetAttribute("name")
			$sType = $oFieldNode.GetAttribute("type")
			$sFields &= $sName & ", "
		Next
		$sFields = StringTrimRight($sFields, 2)
		
		$sQuery = "CREATE TABLE " & $sTableName & " (" & $sFields & ");"
		;ConsoleWrite($sQuery & @CRLF)
	 Next
	 ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)
EndFunc

Func _GetTableQuery_IgRo($sXSD)
	ConsoleWrite("=====IgRo===" & @CRLF)
	Local $Timer = TimerInit()
	;удаляем теги за исключением содержащих "xs:element name="
	$sXSD = StringRegExpReplace($sXSD, '<(?!/?xs:element)[^<>]+>\v*', '')
	;удаляем теги содержащие "xs:element msdata"
	$sXSD = StringRegExpReplace($sXSD, '\s*<xs:element.+msdata[^<>/]+>\v*', '')
	;удаляем слова
	$sXSD = StringRegExpReplace($sXSD, '(form="unqualified")|(minOccurs="0")', '')
	;удаляем пробелы в начале строки 
	$sXSD = StringRegExpReplace($sXSD, '(?s)(\s[^\n])+<', '<')
	;таблица с именем
	$sXSD = StringRegExpReplace($sXSD, '<xs:element name="(.*)"\s?>', 'CREATE TABLE $1 (')
	;имена полей
	$sXSD = StringRegExpReplace($sXSD, '\v*<xs:element name="', '')
	$sXSD = StringRegExpReplace($sXSD, '"\s*type="xs:string"\s*/>', ', ')
	;конец таблицы
	$sXSD = StringRegExpReplace($sXSD, ', (\s*</xs:element>\s?)+', ');')
	;ConsoleWrite($sXSD & @CRLF)
	ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)
EndFunc
но время на мелком файле наверное не показатель
у XpycTа стабильнее работа при модефикацииях XSD
 

xaker

Знающий
Сообщения
52
Репутация
16
можно просто многократно проверять :
Код:
#include <array.au3>

Dim $s_File = "2.xsd"
Dim $i_Enc, $h_File, $s_Text
$i_Enc = FileGetEncoding($s_File)
$h_File = FileOpen($s_File, $i_Enc)
$sXSD = FileRead($h_File)
FileClose($h_File)

$x = 1000 ; количество циклов

$oXML = ObjCreate('Microsoft.XMLDOM')

ConsoleWrite("===xaker=====" & @CRLF)
$Timer = TimerInit()
For $i = 1 To $x
	_GetTableQuery_xaker($sXSD)
Next
ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)

ConsoleWrite("===XpycT=====" & @CRLF)
$Timer = TimerInit()
For $i = 1 To $x
	_GetTableQuery_XpycT($sXSD)
Next
ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)

ConsoleWrite("=====IgRo===" & @CRLF)
$Timer = TimerInit()
For $i = 1 To $x
	_GetTableQuery_IgRo($sXSD)
Next
ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)

;~ _GetTableQuery_xaker($sXSD)
;~ _GetTableQuery_XpycT($sXSD)
;~ _GetTableQuery_IgRo($sXSD)

Func _GetTableQuery_xaker($sXSD)
;~  ConsoleWrite("===xaker=====" & @CRLF)
;~ Local $Timer = TimerInit()
   $test=StringRegExp($sXSD, '(?s)<xs:sequence>(.*?)</xs:sequence>', 3)
   $test2 = StringRegExp($sXSD, '<xs:element name="(.*?)"\s*form="unqualified">\R\s*<xs:complexType>', 3)
   For $i = 0 To UBound($test) - 1
       $test[$i] = StringRegExp( $test[$i], '<xs:element name="(.*?)"', 3)
       $test[$i] = 'CREATE TABLE ' & $test2[$i] & ' (' & _ArrayToString( $test[$i], ', ') & ');'
   Next
;~    $sQuery=_ArrayToString( $test, ';'&@CRLF)
   ;ConsoleWrite($sQuery & @CRLF)
;~    ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)
EndFunc


Func _GetTableQuery_XpycT($sXSD)
;~     ConsoleWrite("===XpycT=====" & @CRLF)
    Local $Timer = TimerInit()

    $oXML.LoadXML($sXSD)
    $XPath = "xs:schema"
    $XPath &= "/xs:element"
    $XPath &= "/xs:complexType"
    $XPath &= "/xs:choice"
    $XPath &= "/xs:element" ;Data
    $XPath &= "/xs:complexType"
    $XPath &= "/xs:sequence"
    $XPath &= "/xs:element" ;Таблицы
    $oTableNodes = $oXML.SelectNodes($XPath)
    If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oTableNodes | Error > " & $oXML.ParseError.Reason & @CR)
    For $iTable = 0 To $oTableNodes.Length -1
        $sTableName = $oTableNodes.Item($iTable).GetAttribute("name")
        ; 1 вариант
;~      $XPath &= "[" & $iTable & "]/xs:complexType"
;~      $XPath &= "/xs:sequence"
;~      $XPath &= "/xs:element"
;~      $oFieldNodes = $oXML.SelectNodes($XPath)
;~      If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oFieldNodes v1 | Error > " & $oXML.ParseError.Reason & @CR)
        ; 2 вариант
        $oFieldNodes = $oTableNodes.Item($iTable).ChildNodes().Item(0).ChildNodes().Item(0).ChildNodes()
        If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oFieldNodes v2 | Error > " & $oXML.ParseError.Reason & @CR)
        $sFields = ""
        For $oFieldNode In $oFieldNodes
            $sName = $oFieldNode.GetAttribute("name")
            $sType = $oFieldNode.GetAttribute("type")
            $sFields &= $sName & ", "
        Next
        $sFields = StringTrimRight($sFields, 2)

        $sQuery = "CREATE TABLE " & $sTableName & " (" & $sFields & ");"
        ;ConsoleWrite($sQuery & @CRLF)
     Next
;~      ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)
EndFunc

Func _GetTableQuery_IgRo($sXSD)
;~     ConsoleWrite("=====IgRo===" & @CRLF)
    Local $Timer = TimerInit()
    ;удаляем теги за исключением содержащих "xs:element name="
    $sXSD = StringRegExpReplace($sXSD, '<(?!/?xs:element)[^<>]+>\v*', '')
    ;удаляем теги содержащие "xs:element msdata"
    $sXSD = StringRegExpReplace($sXSD, '\s*<xs:element.+msdata[^<>/]+>\v*', '')
    ;удаляем слова
    $sXSD = StringRegExpReplace($sXSD, '(form="unqualified")|(minOccurs="0")', '')
    ;удаляем пробелы в начале строки
    $sXSD = StringRegExpReplace($sXSD, '(?s)(\s[^\n])+<', '<')
    ;таблица с именем
    $sXSD = StringRegExpReplace($sXSD, '<xs:element name="(.*)"\s?>', 'CREATE TABLE $1 (')
    ;имена полей
    $sXSD = StringRegExpReplace($sXSD, '\v*<xs:element name="', '')
    $sXSD = StringRegExpReplace($sXSD, '"\s*type="xs:string"\s*/>', ', ')
    ;конец таблицы
    $sXSD = StringRegExpReplace($sXSD, ', (\s*</xs:element>\s?)+', ');')
    ;ConsoleWrite($sXSD & @CRLF)
;~     ConsoleWrite('Time ' & TimerDiff($Timer) / 1000 & " s." & @CRLF)
EndFunc
 
Автор
I

IgRo

Знающий
Сообщения
65
Репутация
5
xaker ёще на Tree.xsd не работает :blum:
так лишнее хватает
Код:
'<xs:element name="(.*?)"(\s*form="unqualified")?>\R\s*<xs:complexType>'
При импорте большого XML создаем схему с помошью
с XSD схемами скорость не важна они похожи на "кощееву смерть" но имеют не большой размер, а при обработке XML с большим количеством записей скорость необходима!!! Ранее приведен пример обработки XML c помощью XMLDOM и RegExp разница в 20 раз при этом RegExp`ы явно не оптимальны.
 

xaker

Знающий
Сообщения
52
Репутация
16
интересно каким способом XMLDOM обрабатывает текст, регулярками ?
 
Верх