parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

как я делал импорт XML от клиента в базу (очень просто, и годится для не очень больших объёмов)

Александр Петросян (PAF) 31.01.2003 11:14 / 31.01.2003 11:17

описывал таблицу: имена, типы данных и xpath для получения колонки.
после чего напускал XSL transform, получал… код на Parser с SQL командами внутри ;) этот код компилировал и выполнял.

таблица описания входного файла и создаваемой таблицы в базе:
name	type	size	valueXPath	node
card_id	integer		@id	Holder
login_name	varchar	20	ACL/Login	
login_password	varchar	20	ACL/Password	
person_first_name	varchar	50	PersonalData/Initials/FirstName	
person_middle_name	varchar	50	PersonalData/Initials/MidName	
person_last_name	varchar	50	PersonalData/Initials/LastName	
person_email	varchar	100	PersonalData/EMail	
card_name	varchar	101	CardData/CardName	
card_number	varchar	20	CardData/CardNumber	
balance	integer		Balance	
соответственно, мы можем и программно создать нужную таблицу (на случай, если формат поменяется) и относительно несложно вести сам импорт.

вот не жалко:
# Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)

@auto[]
$field[^table::load[card/card.cfg]]
#^create-mysql[]
$ignore_sequence(1)

@create-mysql[]
^^void:sql{
	drop table card
}	
^^void:sql{
    create table card (
	^field.menu{
		$field.name $field.type 
		^if($field.size){($field.size)}
		^if(^field.offset[]==0){not null primary key}
	}[,]
    )
}
^^void:sql{
	drop table card_sequence
}
^^void:sql{
	create table card_sequence (
		card_sequence_expect_no double
	)
}
^^void:sql{
	insert into card_sequence values (1)
}

@isCard[letter] true when letter is holder update
#^throw[x;'$letter.file.value.name']
$ext[^file:justext[$letter.file.value.name]]
#^throw[x;'$ext']
$result(^ext.lower[] eq pgp)

@doCard[letter]
$letter_file_name[^file:basename[$letter.file.value.name]]
#^if(^file:justext[$letter_file_name] eq pgp){
#	encrypted, decrypt
	$decrypt[^file::exec[card/gpg.sh;
		$.stdin[$letter.file.value]
		;--no-secmem-warning;--skip-verify;--homedir=/.../secure;--decrypt;-]]
	^if($decrypt.status){
		^throw[decrypt.error;status=$decrypt.status, stderr=$decrypt.stderr]
	}
	$letter_text[$decrypt.text]
#}

$parts[^letter_file_name.match[(\d+)][g]]
$letter_sequence_no($parts.1)
$card_sequence_expect_no(^double:sql{select card_sequence_expect_no from card_sequence})
#^throw[test;^card_sequence_expect_no.format[%.0f]]
^if(!$ignore_sequence){
    ^if($letter_sequence_no < $card_sequence_expect_no){
    	^throw[mail.ignored;received sequence# < expected (^letter_sequence_no.format[%.0f] < ^card_sequence_expect_no.format[%.0f])]
    }
    ^if($letter_sequence_no > $card_sequence_expect_no){
    	^log[warning;mail.gap;received sequence# > expected (^letter_sequence_no.format[%.0f] > ^card_sequence_expect_no.format[%.0f])]
    }
}

^process{
	^script[^xdoc::create{^untaint{$letter_text}}]
}

^void:sql{update card_sequence 
	set card_sequence_expect_no=^letter_sequence_no.format[%.0f]+1
}

^log[success;$updateType#^letter_sequence_no.format[%.0f];$updateCount records from $letter.from $decrypt.stderr]

@script[input]
#^input.save[card/input.txt]
$stylesheet[^xdoc::create{<?xml version="1.0" encoding="$request:charset" ?>
<s:stylesheet xmlns:s="http://www.w3.org/1999/XSL/Transform" version="1.0">

	<s:template match="$field.node">
	
		^^void:sql{delete from card where $field.name=<s:value-of select="$field.valueXPath"/>}
		^^void:sql{
			insert into card values (
				^field.menu{
					$around[^if($field.type eq varchar){'}]
					$around<s:value-of select="$field.valueXPath"/>$around
				}[,]
			)
		}
			
	</s:template>

	<s:template match="/Body">
		^^throw[mail.format^;invalid update type <s:value-of select="@type"/>]
	</s:template>

	<s:template match="/Body[@type='UPDATE' or @type='FULL']">
		<s:if test="@type='FULL'">
			^^void:sql{delete from card}
		</s:if>
		<s:variable name="nodes" select="$field.node"/>
		<s:apply-templates select="^$nodes"/>
		^$updateType[<s:value-of select="@type"/>]
		^$updateCount(<s:value-of select="count(^$nodes)"/>)
	</s:template>

</s:stylesheet>
}]
#^stylesheet.save[card/generated.xsl]

$output[^input.transform[$stylesheet]]
#^output.save[card/output.txt]
^output.string[
	$.mode[xml]
]