0 / 0 / 0
Регистрация: 10.02.2024
Сообщений: 39
1

Нежелательное задвоение при парсинге XML

10.02.2024, 08:00. Показов 2045. Ответов 45
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день. У меня проблема при парсинге XML. Суть в том что большинство файлов которые я обрабатываю имеют структуру:
заказ (номер) - товарная накладная (номер) - товар один или много. В данном случае все норм.
Но есть некоторые документы где в заказе две товарных накладных. Изза этого товар задваивается на то количество, сколько товарных накладных. Взгляните на файл пожалуйста, станет понятно, там оба варианта.
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[xml]$xml = Get-Content C:\Users\пк\Downloads\2.xml
$list = @()
$list = $NULL
foreach ($Doc in $xml.GetElementsByTagName('Документы'))
{
    foreach ($Orders in $Doc.GetElementsByTagName('Заказы'))
    {
        foreach ($Order in $Orders.GetElementsByTagName('Заказ'))
        {
            foreach ($TN in $order.GetElementsByTagName('ТоварнаяНакладная'))
            {
            foreach ($TT in $order.GetElementsByTagName('ТорговаяТочка'))
            {
            foreach ($Products in $order.GetElementsByTagName('Товары'))
            {
                foreach ($Product in $Products.GetElementsByTagName('Товар'))
                {
                           
                           $list += [PSCustomObject]@{
                                ТорговыйАгент = $TT.ТорговыйАгент
                                Номенклатура = $Product.Номенклатура
                                НомерЗаказа = $Order.НомерЗаказа
                            }
                 }
             }
             }
             }
        }
    }
 
}
$list
Задача: Если в заказе две или больше товарных накладных, то их номера должны быть перечислены через запятую в, а товары не задваиватся.
Пните в правильном направлении.
Вложения
Тип файла: 7z 2.7z (843 байт, 20 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.02.2024, 08:00
Ответы с готовыми решениями:

Ошибка при парсинге XML
Досталась XML'ка с ошибкой, каждое случайно число строк (зависимость не искали), появляется какой...

Кириллица при парсинге XML
Приветствую всех! Пишу программу на Android. В программе закачиваю из интернета XML: <trk> ...

Ошибка при парсинге XML
День добрый имеется вот такой xml: <?xml version="1.0"?> <urlset...

неверная кодировка при парсинге xml
доброго времени суток сделал парсинг xml допустим есть 2 сайта domain.com - где лежит некий...

45
Нарушитель
5750 / 1927 / 320
Регистрация: 10.12.2013
Сообщений: 6,704
10.02.2024, 16:33 2
структура данных должна быть адаптирована под конкретную задачу.

целевая задача какая? иными словами, что будешь делать с этими данными после разбора XML ?

Добавлено через 1 час 47 минут
Цитата Сообщение от sergey020487 Посмотреть сообщение
$list = @()
$list = $NULL
второе присвоение здесь отвергает первое.
если переменной присваивают значение $null, она превращается в НИЧТО.

Добавлено через 9 минут
и, да, первое присвоение отработает

$list += [pscustomobject]@{...}

и переменная $list получит вместо НИЧТО тип 'pscustomobject',
но второе присвоение

$list += [pscustomobject]@{...}

уже не отработает, поскольку оператор сложения '+' для типа 'pscustomobject' не определён.

( в моей версии 7.3 именно так, вылетит с ошибкой
InvalidOperation: Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named 'op_Addition'.
)
1
1186 / 285 / 92
Регистрация: 26.09.2020
Сообщений: 613
10.02.2024, 17:01 3
sergey020487, не очень понял, чего требуется. Может образец желаемого результата помог бы…
PowerShell
1
2
3
4
5
6
7
8
$xml.Документы.Заказы.Заказ.ForEach({
    [PSCustomObject]@{
        ТорговыйАгент     = $_.ТорговаяТочка.ТорговыйАгент
        Номенклатура      = $_.Товары.Товар.ForEach({ $_.Номенклатура }) -join ', '
        НомерЗаказа       = $_.НомерЗаказа
        ТоварнаяНакладная = $_.ТоварнаяНакладная.ForEach({ $_.Номер }) -join ', '
    }
})
1
1263 / 471 / 136
Регистрация: 20.02.2019
Сообщений: 2,393
Записей в блоге: 42
11.02.2024, 07:02 4
sergey020487, Добрый день, Вы входите в интересную тему, рекомендую все таки немного обратиться к теории перед тем как приступать к практике.

XML документ который вы парсите содержит объекты. Динамическая типизация powershell позволяет вам не особо задумываясь о структуре этих объектов и разобрать их в объекты в памяти.

Мне нравится предложенный iNNOKENTIY21 вариант использовать [PSCustomObject] для этих целей.

Но как и сказал volodin661 почти все тут зависит от задачи которую вы планируете делать.

ИМХО Наиболее корректный подход, это описание структуры объектов в виде соответствующих классов.

Например:


PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Document {
    [Order[]]$Orders
    [Prosuct[]]$Products
}
 
class Order {
    [string]$Number
    [string]$Header
    [string]$Body
}
 
class Prosuct {
    [string]$Number
    [string]$Header
    [string]$Body
}
Но тут мы уже уходим в области для которых PowerShell уже не задумывался, например из за отсутствия возможности реализовывать интерфейсы.

XML уже загружен в память в виде экземпляра объекта который содержит все нужные вам данные и возможно для вашей задачи этого уже достаточно, вы можете обращаться к значениям узлов и атрибутов используя XPath.

А вот засунуть в одну строку несколько значений через запятую идея неочевидная, чтобы обратиться к значению нужно будет парсить эту строку.

Первая нормальная форма
0
Любознательный
5349 / 1592 / 303
Регистрация: 10.03.2016
Сообщений: 3,605
11.02.2024, 08:11 5
Цитата Сообщение от alhaos Посмотреть сообщение
например из за отсутствия возможности реализовывать интерфейсы.
ась, кого позвать?
Создание пользовательского интерфейса
Современный PowerShell (книга - на продаже)
0
1263 / 471 / 136
Регистрация: 20.02.2019
Сообщений: 2,393
Записей в блоге: 42
11.02.2024, 11:25 6
YuS_2, Да, я тут не совсем прав, всегда можно можно вызвать кусок кода на C# и определить в нем интерфейс например, о чем прямо в доке ... написано и да можно писать на PwSh и большие серьезные функционалы, наверное...

Я о том что насколько это уместно что-ли, вот в "Побег из Шоушенка" правдоподобно описан случай когда геологическим молотком Дюфрейн прокопал тоннель, и в его случае это было более чем оправданно. Но я думаю мало кого вдохновила эта сцена на рытье тоннелей подобным способом в обычной обстановке.
0
Любознательный
5349 / 1592 / 303
Регистрация: 10.03.2016
Сообщений: 3,605
11.02.2024, 12:50 7
Цитата Сообщение от alhaos Посмотреть сообщение
Да
Да, говоря об интерфейсе, необходимо таки уточнять о каких интерфейсах речь...

Цитата Сообщение от alhaos Посмотреть сообщение
Я о том что насколько это уместно что-ли
И да, это тоже... распарсить xml и для этого запускать классы с наследованием и интерфейсами... а задача-то конечная какая?

Добавлено через 37 минут
А вообще, странно это:
Implementing interfaces
0
Нарушитель
5750 / 1927 / 320
Регистрация: 10.12.2013
Сообщений: 6,704
11.02.2024, 14:54 8
о как..
интерпейсы и наследование в ход пошли.
соскучились пацаны по большому программированию.
0
0 / 0 / 0
Регистрация: 10.02.2024
Сообщений: 39
12.02.2024, 15:16  [ТС] 9
volodin661, iNNOKENTIY21, alhaos, YuS_2,
Прошу прощения, запостил ерунду.
И так, вот например выполняя данный код получаю задвоенный результат. Сколько Товарных накладных в одном заказе, токое количество и задвоений получается. Тоесть в конечном результате должнор быть: один заказ одна строчка результата, суммы должны складываться, строки отражаться через запятую. Дальше эти данные я буду передавать параметрами в SQL там хранимая процедура ждет данных и инсертит в БД. Я хочу на PS написать чисто парсер XML. Но вот сталкнулся с этой проблемой. На фото слева то что выполняется сейчас моим кодом, справа чего я хотел бы.
Код исправленный (исключительно для формирования хоть какого-то результата, если есть другие объекты, более интересные предлагайте):
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[xml]$xml = Get-Content C:\Users\пк\Downloads\2.xml
$list = @()
 
foreach ($Doc in $xml.GetElementsByTagName('Документы'))
{
    foreach ($Orders in $Doc.GetElementsByTagName('Заказы'))
    {
        foreach ($Order in $Orders.GetElementsByTagName('Заказ'))
        {
            foreach ($TN in $order.GetElementsByTagName('ТоварнаяНакладная'))
            {
            foreach ($TT in $order.GetElementsByTagName('ТорговаяТочка'))
            {
            foreach ($Products in $order.GetElementsByTagName('Товары'))
            {
                foreach ($Product in $Products.GetElementsByTagName('Товар'))
                {
                           
                           $list += [PSCustomObject]@{
                                ЗаказРуб = $Product.ЗаказРуб
                                Номер = $TN.Номер
                                НомерЗаказа = $Order.НомерЗаказа
                            }
                 }
             }
             }
             }
        }
    }
 
}
$list
Миниатюры
Нежелательное задвоение при парсинге XML  
0
Нарушитель
5750 / 1927 / 320
Регистрация: 10.12.2013
Сообщений: 6,704
12.02.2024, 17:11 10
Цитата Сообщение от sergey020487 Посмотреть сообщение
Я хочу на PS написать чисто парсер XML.
чистопарсер xml уже написан.

просто передавай в хранимую процедуру полученные данные.

никакого 'задвоения' нет.

если получено два одинаковых яйца ( это тема очень близка росиянину ),
значит можно приготовить омлет из двух яиц вне зависимости от номера накладной.
из накладной омлет не приготовить.
0
Любознательный
5349 / 1592 / 303
Регистрация: 10.03.2016
Сообщений: 3,605
12.02.2024, 17:59 11
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
function Get-Order ($arr) {
    $arr|%{
        [pscustomobject]@{
            'IDorder' = $_.номерзаказа
            'Num' = $_.товарнаянакладная.номер -join ','
            'Sum' = ($_.товары.товар.заказруб|measure -sum).sum
        }
    }
}
 
$pth = '2.xml'
[xml]$xml = gc $pth -enc utf8
$xml.selectnodes("//Заказ")|%{get-order $_}
1
0 / 0 / 0
Регистрация: 10.02.2024
Сообщений: 39
12.02.2024, 18:01  [ТС] 12
volodin661, Но цель моя не достигнута, как на основании данных из одного столбца (в моем случае это заказы) сгруппировать другой столбец взяв имена и перечислив их через запятую (товарная накладная). и уже эти данные передать в процедуру. С передачей проблем нет, не могу понять как правильно группировать.
0
Любознательный
5349 / 1592 / 303
Регистрация: 10.03.2016
Сообщений: 3,605
12.02.2024, 18:03 13
Цитата Сообщение от volodin661 Посмотреть сообщение
интерпейсы и наследование в ход пошли.
пейсам сейчас не до того, а интер - тем более
0
0 / 0 / 0
Регистрация: 10.02.2024
Сообщений: 39
12.02.2024, 18:05  [ТС] 14
YuS_2, Спасибо большое, то что нужно. Буду разбираться.
0
Нарушитель
5750 / 1927 / 320
Регистрация: 10.12.2013
Сообщений: 6,704
12.02.2024, 18:32 15
sergey020487,

на выходе у тебя массив об'ектов. Со свойствами.

Свойство Номер( Номер Накладной) ты теперь уже ( в последней версии ) вставил.

Ну и зачем их группировать/перечислять ? Прям так и отправляй в храним. процедуру, она разберётся.
1
0 / 0 / 0
Регистрация: 10.02.2024
Сообщений: 39
12.02.2024, 19:00  [ТС] 16
volodin661, Ну группировать то все равно придется, и названия накладной перечеслять тоже придется, либо это делать в шеле либо в скуле, хотел сделать сразу в шеле. Или я не правильно понял?
0
1263 / 471 / 136
Регистрация: 20.02.2019
Сообщений: 2,393
Записей в блоге: 42
12.02.2024, 19:22 17
sergey020487, вы бы все таки пробему х бы обозначили, телепатить не охота


YuS_2, я бы все в функцию убрал...

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
$doc = [xml]@"
<?xml version="1.0" encoding="UTF-8"?>
<Документы>
    <Заказы>
        <Заказ>
            <НомерЗаказа>8928</НомерЗаказа>
            <ДатаЗаказа>2023-10-15</ДатаЗаказа>
            <ТоварнаяНакладная>
                <Номер>ФГ7</Номер>
                <Дата>2023-10-17</Дата>
            </ТоварнаяНакладная>
            <ТоварнаяНакладная>
                <Номер>BP2</Номер>
                <Дата>2023-10-24</Дата>
            </ТоварнаяНакладная>
            <ТорговаяТочка>
                <ИНН>6565656565</ИНН>
                <Супервайзер />
                <Мерчендайзер />
                <ТорговыйАгент>ФИО</ТорговыйАгент>
                <ДолжностьТорговогоАгента> представитель</ДолжностьТорговогоАгента>
                <СубъектФедерации />
                <Адрес>адрес</Адрес>
                <Контрагент>ИП</Контрагент>
                <КаналСбыта />
            </ТорговаяТочка>
            <Товары>
                <Товар>
                    <ЗаказКг>8.400</ЗаказКг>
                    <ЗаказРуб>2772.00</ЗаказРуб>
                    <ОтгрузкаКг>10.460</ОтгрузкаКг>
                    <ОтгрузкаРуб>3451.80</ОтгрузкаРуб>
                    <ПродажаКг>10.460</ПродажаКг>
                    <ПродажаРуб>3451.80</ПродажаРуб>
                    <СредняяЦенаРуб>0.00</СредняяЦенаРуб>
                    <КодНоменклатуры>200017</КодНоменклатуры>
                    <Номенклатура>Товар1</Номенклатура>
                    <Бонус>0</Бонус>
                </Товар>
                <Товар>
                    <ЗаказКг>4.000</ЗаказКг>
                    <ЗаказРуб>1448.00</ЗаказРуб>
                    <ОтгрузкаКг>4.194</ОтгрузкаКг>
                    <ОтгрузкаРуб>1518.23</ОтгрузкаРуб>
                    <ПродажаКг>4.194</ПродажаКг>
                    <ПродажаРуб>1518.23</ПродажаРуб>
                    <СредняяЦенаРуб>0.00</СредняяЦенаРуб>
                    <КодНоменклатуры>200031</КодНоменклатуры>
                    <Номенклатура>Товар2</Номенклатура>
                    <Бонус>0</Бонус>
                </Товар>
                <Товар>
                    <ЗаказКг>4.000</ЗаказКг>
                    <ЗаказРуб>1448.00</ЗаказРуб>
                    <ОтгрузкаКг>4.194</ОтгрузкаКг>
                    <ОтгрузкаРуб>1518.23</ОтгрузкаРуб>
                    <ПродажаКг>4.194</ПродажаКг>
                    <ПродажаРуб>1518.23</ПродажаРуб>
                    <СредняяЦенаРуб>0.00</СредняяЦенаРуб>
                    <КодНоменклатуры>200031</КодНоменклатуры>
                    <Номенклатура>Товар3</Номенклатура>
                    <Бонус>0</Бонус>
                </Товар>
            </Товары>
        </Заказ>
        <Заказ>
            <НомерЗаказа>8966</НомерЗаказа>
            <ДатаЗаказа>2023-10-15</ДатаЗаказа>
            <ТоварнаяНакладная>
                <Номер>9299</Номер>
                <Дата>2023-10-20</Дата>
            </ТоварнаяНакладная>
            <ТорговаяТочка>
                <ИНН>3232323232</ИНН>
                <Супервайзер />
                <Мерчендайзер />
                <ТорговыйАгент>ФИО2</ТорговыйАгент>
                <ДолжностьТорговогоАгента>представитель</ДолжностьТорговогоАгента>
                <СубъектФедерации />
                <Адрес>Адрес</Адрес>
                <Контрагент>ИП2</Контрагент>
                <КаналСбыта />
            </ТорговаяТочка>
            <Товары>
                <Товар>
                    <ЗаказКг>8.400</ЗаказКг>
                    <ЗаказРуб>2772.00</ЗаказРуб>
                    <ОтгрузкаКг>10.460</ОтгрузкаКг>
                    <ОтгрузкаРуб>3451.80</ОтгрузкаРуб>
                    <ПродажаКг>10.460</ПродажаКг>
                    <ПродажаРуб>3451.80</ПродажаРуб>
                    <СредняяЦенаРуб>0.00</СредняяЦенаРуб>
                    <КодНоменклатуры>00017</КодНоменклатуры>
                    <Номенклатура>Товар4</Номенклатура>
                    <Бонус>0</Бонус>
                </Товар>
            </Товары>
        </Заказ>
    </Заказы>
</Документы>
"@
 
function parseDoc {
    [CmdletBinding()]
    param (
        [xml]$d
    )
    $d.SelectNodes("//Заказ").ForEach{
        [pscustomobject]@{
            'ЗаказРуб' = ($_.Товары.Товар.ЗаказРуб | Measure-Object -Sum).Sum
            'Номер' = $_.ТоварнаяНакладная.Номер -join ","
            'НомерЗаказа' = $_.НомерЗаказа
        }
    }
}
 
parseDoc $doc
Код
ЗаказРуб Номер   НомерЗаказа
-------- -----   -----------
 5668,00 ФГ7,BP2 8928
 2772,00 9299    8966
1
Любознательный
5349 / 1592 / 303
Регистрация: 10.03.2016
Сообщений: 3,605
12.02.2024, 19:27 18
Цитата Сообщение от alhaos Посмотреть сообщение
я бы все в функцию убрал
это уже детали... кому как удобно, да хоть в класс можно поместить.
0
Нарушитель
5750 / 1927 / 320
Регистрация: 10.12.2013
Сообщений: 6,704
12.02.2024, 19:42 19
sergey020487,

общей задачi не знаю,
но процедуру отправки данных в mssql я бы тоже сделал в powershell и
безо всяких хранимых процедур.
чтоб всё в одном месте;
заказ разобрал -> сразу запихал, заказ разобрал -> запихал, заказ разобрал -> запихал

то есть, намекаю на то, что массив из об'ектов здесь не нужен.
0
1263 / 471 / 136
Регистрация: 20.02.2019
Сообщений: 2,393
Записей в блоге: 42
12.02.2024, 20:12 20
YuS_2, я и говорил про детали.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.02.2024, 20:12
Помогаю со студенческими работами здесь

Ошибка при парсинге xml с BeautifulSoup
Небходимо спарсить страницу http://econym.org.uk/gmap/states.xml Что-то делаю не так. Объект BS...

Вытащить атрибут при парсинге xml
День добрый, надо распарсить xml документ и все получилось, кроме одного: не могу вытащить атрибут...

Ошибка при парсинге xml файла
Добрый день! При парсинге xml файла возникает ошибка, при чем возникает по середине процесса...

Ошибка при парсинге большого XML (190МБ)
Здравствуйте. При переносе магазина на другой vps сервер столкнулся с ошибкой в парсере xml файла...

Проблема получения атрибутов при парсинге xml
Здравствуйте. Подскажите как разобраться xml документом. У меня есть xsd-схема: &lt;?xml version =...

Преобразование дат при парсинге xml в mssql
Добрый день. Разбираю xml sql сервером. В xml есть список нодов с датам и значениями. Мне нужно...

Linq to XML - убрать лишние теги при парсинге
Здравствуйте, не могли бы вы мне помочь пожалуйста. Я пытаюсь распарсить страницу, но вот одна...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru