XML 到 XML XSLT 转换。 VBScript 中的 MSXML
XML to XML XSLT transformation. MSXML in VBScript
我有一个相当嵌套的 XML 文件,我想使用 XSL 模板将其转换为更简单的文件,以便更高效地将数据批量加载到 SQL 中。我想用 C++(Codeblocks with gcc)来做,但我遇到了一点麻烦,就是无法使用我遇到的任何库(包括 MSXML)加载文档。如果有人有在 Codeblocks 中使用 MSXML 和 gcc 的经验,请告诉我!
我有一个样式sheet,它使用 DOMDocument 转换 Excel VBA 中的 XML,但我不想依赖 Excel .我认为下一个最好的东西是 VBScript。
数据是保存在 <DATAVALUE>
个节点中的一两个文本值,这些节点是 100 个 <LOCATION>
节点的后代。每个 <LOCATION>
节点的第一个 child,称为 <LOCATIONNAME>
,为每个 <LOCATION>
节点保存一个唯一的名称(即 NAME1
-NAME100
) . <LOCATION>
节点的第三个和第四个children(如果有第四个child)是<DATA>
个节点,每个节点持有一个<DATAVALUE>
个节点。该文件可以有超过 100 万个 <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>
节点来完成的。例如,在转换后的sheet中出现两次的<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
错误:
Line: 19
Char: 1
Error: The stylesheet does not contain a document element. The
stylesheet may be empty, or it may not be a well-formed XML document.
Code: 80004005
Source: msxml3.dll
我猜要么是我的脚本不太正确,要么是我缺少某个设置,导致 objects 和库不匹配,因为我的 VBA 宏转换了 xml 那种风格sheet。有人有主意吗?做这个东西的建议运行?
据我所知,loadXML
接受带有 XML 的字符串。如果您有文件或 URL 需要解析,请使用 load
方法。
我有一个相当嵌套的 XML 文件,我想使用 XSL 模板将其转换为更简单的文件,以便更高效地将数据批量加载到 SQL 中。我想用 C++(Codeblocks with gcc)来做,但我遇到了一点麻烦,就是无法使用我遇到的任何库(包括 MSXML)加载文档。如果有人有在 Codeblocks 中使用 MSXML 和 gcc 的经验,请告诉我!
我有一个样式sheet,它使用 DOMDocument 转换 Excel VBA 中的 XML,但我不想依赖 Excel .我认为下一个最好的东西是 VBScript。
数据是保存在 <DATAVALUE>
个节点中的一两个文本值,这些节点是 100 个 <LOCATION>
节点的后代。每个 <LOCATION>
节点的第一个 child,称为 <LOCATIONNAME>
,为每个 <LOCATION>
节点保存一个唯一的名称(即 NAME1
-NAME100
) . <LOCATION>
节点的第三个和第四个children(如果有第四个child)是<DATA>
个节点,每个节点持有一个<DATAVALUE>
个节点。该文件可以有超过 100 万个 <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>
节点来完成的。例如,在转换后的sheet中出现两次的<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
错误:
Line: 19
Char: 1
Error: The stylesheet does not contain a document element. The stylesheet may be empty, or it may not be a well-formed XML document.
Code: 80004005
Source: msxml3.dll
我猜要么是我的脚本不太正确,要么是我缺少某个设置,导致 objects 和库不匹配,因为我的 VBA 宏转换了 xml 那种风格sheet。有人有主意吗?做这个东西的建议运行?
据我所知,loadXML
接受带有 XML 的字符串。如果您有文件或 URL 需要解析,请使用 load
方法。