我有一个相当嵌套的XML文件,我想使用XSL模板将其转换为更简单的文件,以使将数据批量加载到SQL的效率更高。我想用C ++(带有gcc的代码块)来做,但是我有点麻烦,只能用我遇到的任何库(包括MSXML)加载文档。如果有人有使用gcc在Codeblocks中使用MSXML的经验,请告诉我!
我有一个样式表,可使用DOMDocument转换Excel VBA中的XML,但我不想依赖Excel。我认为下一个最好的东西是VBScript。
数据是<DATAVALUE>
节点中保留的一个或两个文本值,是100个<LOCATION>
节点的后代。每个<LOCATION>
节点的第一个子节点称为<LOCATIONNAME>
,为每个<LOCATION>
节点保留唯一的名称(即NAME1
-NAME100
)。 <LOCATION>
节点的第三和第四子节点(如果有第四子节点)是<DATA>
节点,每个节点都拥有<DATAVALUE>
节点。该文件最多可以有100万个<SAMPLE>
节点。这是XML:
<?xml version="1.0" encoding="utf-8"?>
<MYImportFile xmlns="urn:myNamespace">
<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文档中,我需要考虑的一件事是<DATA>
中只有一个<LOCATION>
节点时。这是通过将第一个<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:myNamespace" 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行
字符:1
错误:样式表不包含文档元素。的样式表可能为空,或者可能不是格式正确的XML文档。
代码:80004005
来源:msxml3.dll
我猜我的脚本不是很正确,或者我缺少某个设置,导致对象和库不匹配,因为我的VBA宏使用该样式表转换了xml。有人有想法么?建议使此事情运行?
据我记得,loadXML
使用XML字符串。如果您有要解析的文件或URL,请使用load
方法。