Skip to content

Commit 685d75c

Browse files
committed
feat(parser): add CDATA support
1 parent b266e5d commit 685d75c

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

src/XmlSaxParser/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ export class XmlSaxParser {
157157
SaxEventType.Attribute |
158158
SaxEventType.OpenTagStart |
159159
SaxEventType.CloseTag |
160-
SaxEventType.Text,
160+
SaxEventType.Text |
161+
SaxEventType.Cdata,
161162
{ highWaterMark: this.options.highWaterMark ?? 64 * 1024 }
162163
)
163164

@@ -251,8 +252,9 @@ export class XmlSaxParser {
251252
break
252253
}
253254

254-
// Text
255-
case SaxEventType.Text: {
255+
// Text | CDATA
256+
case SaxEventType.Text:
257+
case SaxEventType.Cdata: {
256258
curElText.push((detail as Text).value)
257259
break
258260
}

test/XmlCsvStreamParser/case2.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { parse } from 'csv-parse/sync'
2+
import { stringify } from 'csv-stringify'
3+
import assert from 'node:assert'
4+
import { createReadStream, createWriteStream } from 'node:fs'
5+
import { readFile } from 'node:fs/promises'
6+
import path from 'node:path'
7+
import {
8+
// @ts-expect-error no typings
9+
compose
10+
} from 'node:stream'
11+
import test from 'node:test'
12+
13+
import { parseXmlToCsvRows } from '../../src/index.js'
14+
15+
test('parseXmlToCsvStreams #case2', async () => {
16+
const xmlReadable = createReadStream(
17+
path.join(process.cwd(), 'test/cases/case2.xml')
18+
)
19+
20+
const CASE2_CSV_FILE = path.join(process.cwd(), '__temp/output/case2.csv')
21+
22+
async function* rowsFlatten(src: AsyncGenerator<string[][]>) {
23+
for await (const rows of src) {
24+
for (const row of rows) {
25+
yield row
26+
}
27+
}
28+
}
29+
30+
const composeWriteStream = (fileName: string) =>
31+
compose(rowsFlatten, stringify(), createWriteStream(fileName))
32+
33+
await parseXmlToCsvRows(xmlReadable, [
34+
{
35+
writeable: composeWriteStream(CASE2_CSV_FILE),
36+
mapping: {
37+
collection: 'Корень',
38+
row: 'Корень/Элемент',
39+
colls: [
40+
{
41+
name: 'Описание',
42+
valuePath: 'Корень/Элемент/Описание'
43+
}
44+
]
45+
}
46+
}
47+
])
48+
49+
const categoryCsvTxt = await readFile(CASE2_CSV_FILE, 'utf8')
50+
51+
const categoryCsv = parse(categoryCsvTxt)
52+
53+
assert.deepStrictEqual(
54+
categoryCsv,
55+
[
56+
['Описание'],
57+
[
58+
'<p>Материал ЛДСП</p> <p><span>Угловое завершение может быть использовано со шкафами серии оптима комфорт</span><span></span></p> <p><span>Универсальные полки к Шкафу-купе &laquo;Оптима-2200&raquo;,</span><br><span>подходят ко всем шкафам-купе &laquo;Оптима&raquo; высотой 2м 20см, размещение слева или справа</span></p>'
59+
],
60+
[
61+
'<p><span>Гостиная Авангард&nbsp; &mdash; легкая, но вместе с тем, вместительная композиция в современном стиле.</span></p> <p><span>Поставляется в цвете дуб сонома.</span></p> <p><span>Роликовые направляющие.</span></p> <p><span>Петли без доводчика.</span></p> <p><span>Кромка пластик на видимых элементах.</span></p> <p><span></span></p> <p>Указана цена за комплект стенки с элементами перечисленными ниже.</p>'
62+
],
63+
[
64+
'<p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Допустимая нагрузка: 110 кг (на одну персону).</span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Высота: около 170 мм.</span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px; color: #008000;"><strong>Слои в матрасе снаружи внутрь:</strong></span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"><strong>1) Ткань стеганная Жаккард.</strong></span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Жаккард. гладкая безворсовая ткань сложного плетения, в состав которой входят как синтетические, так и органические волокна. Своеобразный рельефный рисунок, который получается в результате сложного плетения на плотной ткани, напоминает своего рода гобелен. Жаккардовой тканью часто обтягивают матрасы для того, чтобы продлить срок его службы. К тому же применение особой пропитки специальными веществами позволяет избегать появления статического электричества, обеспечивая удобство и комфорт использования.</span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"></span></p> <p style="font-size: 11.111111640930176px;"><strong style="font-size: 13.333333969116211px; line-height: 15.600000381469727px;">2) Пенополиуретан.</strong></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Пенополиуретан, известный под торговым названием "поролон" - мягкая полиуретановая пена, состоящая на 90% из воздуха. Благодаря мелкоячеистой структуре поролон обладает хорошими показателями эластичности и воздухопроницаемости. Вместе с тем он не является долговечным (быстро теряет упругость, крошится), а также способен гореть с выделением вредных веществ.</span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"><strong>2) Ватин - Хлопковое полотно.</strong></span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Хлопковое нетканое волокно (ватин), получаемое из натуральных хлопковых волокон, проходит специальную обработку, затем прессуется и прошивается нитками (холстопрошивное) либо пробивается иглами (иглопробивное) для прочности. Используется в матрасах как дополнительный гигиенический слой, обладающий антиаллергенностью, гигроскопичностью, хорошим пропусканием влаги и воздуха, теплосберегающими свойствами.</span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"><strong>3) Изоляционная прослойка из термоволока. </strong></span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"><strong>4) Пружинный блок Punktoflaex.</strong></span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 13px;">Цвет и текстура чехла может отличаться от фото и образца в магазине.<br>Размеры матраса имеют погрешность +-1,5 см.</p>'
65+
]
66+
],
67+
'should contain csv'
68+
)
69+
})

test/cases/case2.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Корень>
2+
<Элемент>
3+
<Описание>
4+
<![CDATA[ <p>Материал ЛДСП</p> <p><span>Угловое завершение может быть использовано со шкафами серии оптима комфорт</span><span></span></p> <p><span>Универсальные полки к Шкафу-купе &laquo;Оптима-2200&raquo;,</span><br><span>подходят ко всем шкафам-купе &laquo;Оптима&raquo; высотой 2м 20см, размещение слева или справа</span></p> ]]>
5+
</Описание>
6+
</Элемент>
7+
<Элемент>
8+
<Описание>
9+
<![CDATA[ <p><span>Гостиная Авангард&nbsp; &mdash; легкая, но вместе с тем, вместительная композиция в современном стиле.</span></p> <p><span>Поставляется в цвете дуб сонома.</span></p> <p><span>Роликовые направляющие.</span></p> <p><span>Петли без доводчика.</span></p> <p><span>Кромка пластик на видимых элементах.</span></p> <p><span></span></p> <p>Указана цена за комплект стенки с элементами перечисленными ниже.</p> ]]>
10+
</Описание>
11+
</Элемент>
12+
<Элемент>
13+
<Описание>
14+
<![CDATA[ <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Допустимая нагрузка: 110 кг (на одну персону).</span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Высота: около 170 мм.</span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px; color: #008000;"><strong>Слои в матрасе снаружи внутрь:</strong></span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"><strong>1) Ткань стеганная Жаккард.</strong></span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Жаккард. гладкая безворсовая ткань сложного плетения, в состав которой входят как синтетические, так и органические волокна. Своеобразный рельефный рисунок, который получается в результате сложного плетения на плотной ткани, напоминает своего рода гобелен. Жаккардовой тканью часто обтягивают матрасы для того, чтобы продлить срок его службы. К тому же применение особой пропитки специальными веществами позволяет избегать появления статического электричества, обеспечивая удобство и комфорт использования.</span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"></span></p> <p style="font-size: 11.111111640930176px;"><strong style="font-size: 13.333333969116211px; line-height: 15.600000381469727px;">2) Пенополиуретан.</strong></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Пенополиуретан, известный под торговым названием "поролон" - мягкая полиуретановая пена, состоящая на 90% из воздуха. Благодаря мелкоячеистой структуре поролон обладает хорошими показателями эластичности и воздухопроницаемости. Вместе с тем он не является долговечным (быстро теряет упругость, крошится), а также способен гореть с выделением вредных веществ.</span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"><strong>2) Ватин - Хлопковое полотно.</strong></span></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;">Хлопковое нетканое волокно (ватин), получаемое из натуральных хлопковых волокон, проходит специальную обработку, затем прессуется и прошивается нитками (холстопрошивное) либо пробивается иглами (иглопробивное) для прочности. Используется в матрасах как дополнительный гигиенический слой, обладающий антиаллергенностью, гигроскопичностью, хорошим пропусканием влаги и воздуха, теплосберегающими свойствами.</span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"><strong>3) Изоляционная прослойка из термоволока. </strong></span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 11.111111640930176px;"><span style="font-size: small; line-height: 15.600000381469727px;"><strong>4) Пружинный блок Punktoflaex.</strong></span></p> <p style="font-size: 11.111111640930176px;"></p> <p style="font-size: 13px;">Цвет и текстура чехла может отличаться от фото и образца в магазине.<br>Размеры матраса имеют погрешность +-1,5 см.</p> ]]>
15+
</Описание>
16+
</Элемент>
17+
</Корень>

test/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
import './XmlCsvStreamParser/case1.test.js'
2+
import './XmlCsvStreamParser/case2.test.js'

0 commit comments

Comments
 (0)