Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > XML, XSL > xsltproc


Автор: SABROG 4.5.2009, 21:47
Возился сегодня целый день с xsltproc от libxml2. Проблема такая.
Есть xml файл 20Мб. Есть MSSQL сервер. С помощью своего .xsl файла я формирую текстовый файл типа coma separated (почти csv только без кавычек). Нужен этот файлик для BULK INSERT.

Проблема возникла, когда в ключах xml файла стали появляться разные спец.символы - запятая, кавычки, пробелы сразу перед текстом и прочее. Всего таких символов-замены штук 10.

Изначально я столкнулся с первой проблемой - отсутствие string.replace в xsl 1.0. В xsl 2.0 оно есть, но его не держит xsltproc.
На основе шаблонов я сначала нашел многоэтажное решение. Потом узнал о существовании EXSLT.

Как вы понимаете, чтобы заменить 10 разных символов в одной строке - приходится строить вавилонскую башню. Ладно бы ключ один был, так их 17.

При первых испытаниях произошло следующее:
- без replace xml на 20Мб парсится - 15 секунд
- с replace (пока всего один символ) - 40 секунд

Соответственно, чем больше тем хуже. Но я столкнулся с тем, что символы одинарной и двойной кавычки вообще не могу заменить, т.к. xsltproc ругается на них, даже если я экранирую: "'", '"', '\"', "\'", """, "&#xx;" и т.д.

В общем вилы. Думаю сейчас бросить этот злой xslt и парсить самому с помощью C++. 

Может советы у кого есть какие, по-началу то мне возможность подобного преобразования очень понравилась, особенно скорость (без replace)?

Автор: sir_nuf_nuf 4.5.2009, 23:59
как я понял проблему - в делаете CSV файл с помощью XSLT
но есть проблема - в CSV попадаю символы которые имеют специальное значение - типа кавычек.. 

предлагаю:
1) работать с XML с помощью XSLT (а не С++) ибо это удобно.
2) полученый недо-CSV подвергать пост-обработке с целью удаления всех таких артефактов.
Я думаю для этого будет удобно использовать регулярные выражения - это будет быстро.
с помощью чего конкретно - вам на выбор.. sed, perl, awk и т.д.
replace

кстати ваши программы можно будет объединить в pipe
Код

xsltproc your_transform.xslt - |  sed -e 's/ba/bu/g' < your_data.xml > your_data.csv

Автор: SABROG 5.5.2009, 08:34
В варианте с пост-обработкой есть проблема - запятые и пробелы. Например:

Код

AUTHOR,BOOK,ISDN,PRICE


Если при этом будет такое:
Код

No Name, NoBook,ISDN,54,30


То MSSQL сервер выплюнет ошибку на BULK INSERT. Т.к. существуют пробелы после разделительной запятой и присутствует лишний разделитель запятая в цене 54,30.

К тому же "sed -e 's/ba/bu/g'" - заменяет одно вхождение, а у меня массив из 10 таких пар.

Автор: sir_nuf_nuf 5.5.2009, 09:55
SABROG, пожалуй да.. запятые стоит эскейпить еще в XSLT.
Вообще по идее - у вас должно быть всего 2 запрещенных символа в выводе - это тот который используюется как разделитель
строк и тот который используется как разделитель ячеек в строке.
Кстати, а может Mysql понимает табуляцию как разделитель? тогда пропроще будет.

вот вам две замены.
Код

sed -e's/bu/ba/g' -e's/gu/ga/g'

Автор: SABROG 6.5.2009, 08:56
Цитата(sir_nuf_nuf @ 5.5.2009,  09:55)
SABROG, пожалуй да.. запятые стоит эскейпить еще в XSLT.
Вообще по идее - у вас должно быть всего 2 запрещенных символа в выводе - это тот который используюется как разделитель
строк и тот который используется как разделитель ячеек в строке.
Кстати, а может Mysql понимает табуляцию как разделитель? тогда пропроще будет.

вот вам две замены.
Код

sed -e's/bu/ba/g' -e's/gu/ga/g'

Менять MSSQL на MySQL из-за того, что не могу заменить символы в xml smile ?  У нас в базе сейчас 90*6 миллионов записей и 5 лет её заполнения. К тому же клиентский софт коммерческий, работает только с MSSQL, куча PHP скриптов и процедур написано под базу.

2 запрещенных ну никак не получается, т.к. всякие "--","&",""","'" - рушат SQL запрос к базе. А он используется уже после того как сделан BULK INSERET в php скрипте-интерфейсе. Например импортировал я название автора "O'Reilly", потом это название берется из базы и передается на страничку в качестве ссылки. Когда я жму на ссылку оно передается уже в другой SQL запрос. А он рушится из-за того, что не экранирован. Нет, конечно можно экранировать все в PHP скрипте, но их таких много сделанных по образу и подобию. Т.ч. мне проще всё лишнее удалить сразу. Но очень расстраивает, что из-за этого скорость парсинга xml файла падает в 2 раза.

Автор: sir_nuf_nuf 6.5.2009, 11:17
Э.. вы меня не поняли. По поводу MSSQL - я просто не правильно прочитал. Менять ничего не надо

Каким образом вы копируете данные в базу?
http://doc.ddart.net/mssql/sql70/ba-bz_9.htm?

Насколько я понял там используется табуляция как разделитель по умолчанию.
Т.е. у вас ячейки должны быть раделены табом.

Ну вот и разделяйте их так. Совершенно не надо эскейпить все символы.



В конце концов.. создайте таблицу (любую) с несколькими колонками, вставьте в нее всякую чепуху
со спецсимволами и скопируйте в файл - увидите как все должно выглядеть

Автор: SABROG 6.5.2009, 12:29
У нас FIELDTERMINATOR в запятую выставлен. Но как показали опыты наши партнеры могут в xml запихнуть что-нибудь злое, что даже стандартам не соответствует (например текст на русском в кодировке cp1251 в то время как encode у xml'я стоит UTF-8).

Автор: sir_nuf_nuf 6.5.2009, 14:31
SABROG
а) ну лады - в запятую так в запятую. в XSLT - заменяешьвсе запятые и переносы строк на эскейп последовательности.
никак не могу понять зачем ВСЕ спецсимволы эскейпить ? ты же делаешь bulk insert, а не SQL запросы склеиваешь 
б) эх.. ну могу только посучувствовать. А еще ваши партнеры наверняка с этим не будут разбираться ибо нужно это прежде всего вам =) бывает

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)