XML VBA Объединить родительские узлы с одинаковыми значениями
столкнулся с проблемой при экспортировании с помощью VBS скрипта xml-файла, структура имеет данный вид:
<?xml version="1.0" encoding="windows-1251"?>
<Documents>
<Document>
<Header>
<Number>999</Number>
</Header>
<Items>
<Item>
<Code>111</Code>
</Item>
</Items>
</Document>
<Document>
<Header>
<Number>999</Number>
</Header>
<Items>
<Item>
<Code>222</Code>
</Item>
</Items>
</Document>
<Document>
<Header>
<Number>999</Number>
</Header>
<Items>
<Item>
<Code>333</Code>
</Item>
</Items>
</Document>
Требуемый вид:
<?xml version="1.0" encoding="windows-1251"?>
<Documents>
<Document>
<Header>
<Number>999</Number>
</Header>
<Items>
<Item>
<Code>111</Code>
</Item>
<Item>
<Code>222</Code>
</Item>
<Item>
<Code>333</Code>
</Item>
</Items>
</Document>
</Documents>
Таких записей должно быть около 3 тысяч, а из-за дублирования количество растянулось до ~7 тысяч. Я не сильно разбираюсь в VBA (начал изучение 3~4 дня назад), поэтому, не найдя аналогов решения, прошу помочь. Параллельно буду смотреть в сторону XSLT, вдруг решение в нем скрывается.
Ответы (1 шт):
Автор решения: Yitzhak Khabinsky
→ Ссылка
Пожалуйста, попробуйте следующий XSLT.
Входной XML
<?xml version="1.0" encoding="windows-1251"?>
<Documents>
<Document>
<Header>
<Number>999</Number>
</Header>
<Items>
<Item>
<Code>111</Code>
</Item>
</Items>
</Document>
<Document>
<Header>
<Number>999</Number>
</Header>
<Items>
<Item>
<Code>222</Code>
</Item>
</Items>
</Document>
<Document>
<Header>
<Number>999</Number>
</Header>
<Items>
<Item>
<Code>333</Code>
</Item>
</Items>
</Document>
<Document>
<Header>
<Number>770</Number>
</Header>
<Items>
<Item>
<Code>100</Code>
</Item>
</Items>
</Document>
</Documents>
XSLT 1.0
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="windows-1251"/>
<xsl:strip-space elements="*"/>
<xsl:key name="DocumentByNumberIndex" match="Document" use="Header/Number"/>
<xsl:template match="Documents">
<xsl:copy>
<xsl:for-each select="Document[generate-id(.) = generate-id(key('DocumentByNumberIndex', Header/Number))]">
<xsl:sort select="key('DocumentByNumberIndex', Header/Number)/Header" data-type="number"
order="ascending"/>
<Document>
<Header>
<Number>
<xsl:value-of select="key('DocumentByNumberIndex', Header/Number)/Header/Number"/>
</Number>
</Header>
<Items>
<xsl:copy-of select="key('DocumentByNumberIndex', Header/Number)/Items/Item"/>
</Items>
</Document>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Выходной XML
<?xml version='1.0' encoding='windows-1251'?>
<Documents>
<Document>
<Header>
<Number>770</Number>
</Header>
<Items>
<Item>
<Code>100</Code>
</Item>
</Items>
</Document>
<Document>
<Header>
<Number>999</Number>
</Header>
<Items>
<Item>
<Code>111</Code>
</Item>
<Item>
<Code>222</Code>
</Item>
<Item>
<Code>333</Code>
</Item>
</Items>
</Document>
</Documents>
VB Script
xslt.vbs file
Option Explicit
Const strInputFile = "e:\Temp\Input.xml"
Const strTemplateFile = "e:\Temp\Process.xslt"
Const strOutputFile = "e:\Temp\Output.xml"
Dim objXMLDoc : Set objXMLDoc = WScript.CreateObject("Msxml2.DOMDocument")
objXMLDoc.async = False
objXMLDoc.load(strInputFile)
Dim objXSLDoc : Set objXSLDoc = WScript.CreateObject("Msxml2.DOMDocument")
objXSLDoc.async = False
objXSLDoc.load(strTemplateFile)
Dim objNewXMLDoc : Set objNewXMLDoc = WScript.CreateObject("Msxml2.DOMDocument")
objXMLDoc.transformNodeToObject objXSLDoc, objNewXMLDoc
objNewXMLDoc.save strOutputFile
XSLT Launcher.cmd
Для запуска в командной строке.
wscript xslt.vbs