У меня есть довольно вложенный файл XML, который я хотел бы преобразовать с помощью шаблона XSL во что-то немного более простое, чтобы сделать массовую загрузку данных в SQL более эффективной. Я хотел сделать это на C ++ (кодовые блоки с g cc), но у меня возникли некоторые проблемы с возможностью загрузки документа с любой из библиотек, с которыми я сталкивался, включая MS XML. Если у кого-то есть опыт использования MS XML в Codeblocks с g cc, дайте мне знать!
У меня есть таблица стилей, которая преобразует XML в Excel VBA с DOMDocument, но я не хочу зависеть от Excel. Я подумал, что следующим лучшим вариантом будет VBScript.
Данные - это одно или два текстовых значения, которые хранятся в <DATAVALUE>
узлах, потомках 100 <LOCATION>
узлов. Первый дочерний элемент каждого узла <LOCATION>
, называемый <LOCATIONNAME>
, содержит уникальное имя для каждого узла <LOCATION>
(т. Е. NAME1
- NAME100
). Третий и четвертый дочерние узлы <LOCATION>
узла (если есть четвертый дочерний узел) являются <DATA>
узлами, каждый из которых содержит <DATAVALUE>
узел. Файл может иметь более 1 миллиона <SAMPLE>
узлов. Вот XML:
<?xml version="1.0" encoding="utf-8"?>
<MYImportFile xmlns="urn:ohLookHEREaNamespacedeclaration">
<HEADERVERSION>1.10</HEADERVERSION>
<MESSAGE>Import</MESSAGE>
<MYBED>QUEEN</MYBED>
<SOURCE>SPRING </SOURCE>
<USERID>MMOUSE</USERID>
<DATETIME>2019-11-25T12:31:00</DATETIME>
<SAMPLE TYPE="No" APPLE="false">
<SAMPLEID>0000565</SAMPLEID>
<SAMPLECATEGORY>CLASS5</SAMPLECATEGORY>
<LOCATION APPLE="false">
<LOCATIONNAME>NAME1</LOCATIONNAME>
<READBY>MMOUSE</READBY>
<TIME>12:31:00</TIME>
<DATA>
<DATAVALUE>aaaa</DATAVALUE>
</DATA>
<DATA>
<DATAVALUE>bbbb</DATAVALUE>
</DATA>
</LOCATION>
'''''''''''''''''there are 100 LOCATION entries''''''''''''''''''''''''
<LOCATION APPLE="false">
<LOCATIONNAME>NAME100</LOCATIONNAME>
<READBY>MMOUSE</READBY>
<TIME>12:31:00</TIME>
<DATA>
<DATAVALUE>zzzz</DATAVALUE>
</DATA>
</LOCATION>
</SAMPLE>
'''''''''''''''''repeat for however many SAMPLES there are''''''''''''''''''''''
</MYImportFile>
Я хочу кое-что указать, чтобы было немного яснее, что происходит. В преобразованном документе xml я должен учитывать одну вещь, когда в <LOCATION>
есть только один узел <DATA>
. Это делается путем копирования первого узла <DATAVALUE>
во второй узел <DATAVALUE>
в новом документе. Например, <DATAVALUE>
, "zzzz"
, которые появляются дважды в преобразованном листе, появляются только в исходных XML один раз. Вот что я хочу, чтобы преобразованный XML выглядел так:
<?xml version="1.0" encoding="UTF-8"?>
<MYImportFile>
<SAMPLE>
<SAMPLEID>0000565</SAMPLEID>
<NAME1_1>aaaa</NAME1_1>
<NAME1_2>bbbb</NAME1_2>
<NAME2_1>cccc</NAME2_1>
<NAME2_2>dddd</NAME2_2>
'''''''''''''''''there are 100 LOCATION entries transformed to NAME1-NAME100''''''''''''''''''''''''
<NAME100_1>zzzz</NAME100_1>
<NAME100_2>zzzz</NAME100_2>
</SAMPLE>
'''''''''''''''''repeat for however many SAMPLES there are''''''''''''''''''''''
</MYImportFile>
Моя таблица стилей (которая работает с кодом VBA):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:b="urn:ohLookHEREaNamespacedeclaration" exclude-result-prefixes="b">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/b:MYImportFile">
<MYImportFile>
<xsl:for-each select="b:SAMPLE">
<SAMPLE>
<SAMPLEID>
<xsl:value-of select="b:SAMPLEID"/>
</SAMPLEID>
<NAME1_1>
<xsl:value-of select="b:LOCATION/b:LOCATIONNAME[text() = 'NAME1']/../b:DATA[1]/b:DATAVALUE"/>
</NAME1_1>
<xsl:choose>
<xsl:when test="b:LOCATION/b:LOCATIONNAME[text() = 'NAME1']/../b:DATA[2]/b:DATAVALUE">
<NAME1_2>
<xsl:value-of select="b:LOCATION/b:LOCATIONNAME[text() = 'NAME1']/../b:DATA[2]/b:DATAVALUE"/>
</NAME1_2>
</xsl:when>
<xsl:otherwise>
<NAME1_2>
<xsl:value-of select="b:LOCATION/b:LOCATIONNAME[text() = 'NAME1']/../b:DATA[1]/b:DATAVALUE"/>
</NAME1_2>
</xsl:otherwise>
</xsl:choose>
'''''''''''''''''''there are 100 NAME entires to recieve the 100 locations
</SAMPLE>
</xsl:for-each>
</MYImportFile>
</xsl:template>
</xsl:stylesheet>
Мой сценарий:
Option Explicit
Const strInputFile = "C:\Path\fileName.xml"
Const strTemplateFile = "C:\Path\convFileName.xsl"
Const strOutputFile = "C:\Path\newFileName.xml"
Dim objXMLDoc : Set objXMLDoc = WScript.CreateObject("Msxml2.DOMDocument")
objXMLDoc.async = False
objXMLDoc.loadXML(strInputFile)
objXMLDoc.SetProperty "SelectionNamespaces", "xmlns='urn:myNamespace'"
Dim objXSLDoc : Set objXSLDoc = WScript.CreateObject("Msxml2.DOMDocument")
objXSLDoc.async = False
objXSLDoc.loadXML(strTemplateFile)
Dim objNewXMLDoc : Set objNewXMLDoc = WScript.CreateObject("Msxml2.DOMDocument")
objXMLDoc.transformNodeToObject objXSLDoc, objNewXMLDoc
objNewXMLDoc.save strOutputFile
Ошибка:
Строка: 19
Char: 1
Ошибка: таблица стилей не содержит элемент документа. Таблица стилей может быть пустой или неправильной формы XML документ.
Код: 80004005
Источник: msxml3.dll
I Я предполагаю, что либо мой сценарий не совсем правильный, либо есть пропущенная настройка, что приводит к несовпадению объектов и библиотек, потому что мой макрос VBA преобразует xml с этой таблицей стилей. У кого-нибудь есть идеи? Предложения, чтобы заставить эту вещь работать?