【问题标题】:How to solve this specific .xlsx to .xml transformation case?如何解决这个特定的 .xlsx 到 .xml 转换案例?
【发布时间】:2019-12-10 23:29:01
【问题描述】:

我有一个大型 Excel 文件 (.xlsx),其中包含以下列和一些示例内容:

文件非常大,有 981 行。

现在我希望将每一行写入一个单独的 XML 文件,该文件应遵循我确定的特定“模板”。应该是下面这个(没必要通读一遍:))

现在我需要一些代码,让我可以说

  • 对于 .xlsx 文件中的每一行,使用上面的模板生成一个新的 XML 文件
  • Nummer/Kunde/Titel/Datum/System/hh:mm:ss 列中的内容应自动写入以下 XML 标记 [...]
  • 特别的是,正如您在我的模板中看到的那样,大部分 XML 标记已经填写完毕。

但如果你有模板,它就不能正常工作。此代码的第一行描述了 XML 标记。我无法像这样描述我的所有标签,而且我不知道如何判断大多数标签已经被填满。

我对 XSLT 有一些简单的经验,我觉得可以用它完成这项任务,我只是不知道如何。

有人有什么想法吗?谢谢大家! :)

【问题讨论】:

  • 解决方案是否像使用load(从文件加载XML文档)而不是使用loadXML(从字符串加载XML文档)一样简单?
  • 我试图添加行 doc.Load ("//test.xml") (不是真正的路径,只是为了数据保护而修改它)而不是 LoadXML 行之后我到达错误“91”
  • 我的 test.xml 看起来像这样
  • Excel 数据应该映射到您发布的模板中的哪个位置?您的帖子省略了标签:Nummer/Kunde/Titel/Datum/System/hh:mm:ss 列中的内容应自动写入以下 XML 标签 [...]。我什至无法阅读该语言。
  • 由于这不确定(我没有那么具体的原因),因此可以在我自己对该主题的回答中假设示例文件 test.xml。主要问题是完成它,无论是哪个标签。是不是可以把问题抽象一点,专注于工作流程?对不起我的英语不好,谢谢你的帮助!

标签: excel xml vba xslt transformation


【解决方案1】:

考虑一个参数化的 XSLT,您可以在其中迭代 Excel 文件的行并将它们作为参数从 VBA 传递到 XSLT。 Windows 的 MSXML 库通过 processor object 支持此方法。

输入 XML (例如“模板”)

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <nummer></nummer>
    <kunde></kunde>
    <titel></titel>
    <datum></datum>
    <system></system>
    <dauer></dauer>
</root>

XSLT (另存为.xsl文件,特殊的.xml文件)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:param name="nummer" />
    <xsl:param name="kunde" />
    <xsl:param name="titel" />
    <xsl:param name="datum" />
    <xsl:param name="system" />
    <xsl:param name="dauer" />

    <!-- IDENTITY TRANFORM -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/root">
        <xsl:copy>
            <nummer><xsl:value-of select="$nummer"/></nummer>
            <kunde><xsl:value-of select="$kunde"/></kunde>
            <titel><xsl:value-of select="$titel"/></titel>
            <datum><xsl:value-of select="$datum"/></datum>
            <system><xsl:value-of select="$system"/></system>
            <dauer><xsl:value-of select="$dauer"/></dauer>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

VBA (参数名称必须与上面的 XSLT 匹配)

Sub Param_XSLT_Process()
On Error GoTo ErrHandle
    ' ADD REFERENCE Microsoft XML, v6.0
    Dim xmldoc As New MSXML2.DOMDocument60, newDoc As New MSXML2.DOMDocument60
    Dim xslDoc As New MSXML2.FreeThreadedDOMDocument60
    Dim xslTemp As New MSXML2.XSLTemplate60
    Dim xslProc As Object

    Dim lLastRow As Long, lRow As Long

    ' LOAD XML AND XSL FILES
    xmldoc.async = False
    xmldoc.Load "C:\Path\To\Input.xml"

    xslDoc.async = False
    xslDoc.setProperty "AllowDocumentFunction", True
    xslDoc.Load "C:\Path\To\XSLT\Script.xsl"

    ' INITIALIZE NEEDED OBJECTS
    Set xslTemp.stylesheet = xslDoc
    Set xslProc = xslTemp.createProcessor()

    xslProc.input = xmldoc

    ' ITERATE THROUGH EACH ROW, TRANSFORM, SAVE XML OUTPUT
    With ActiveWorkbook.Worksheets(1)
       lLastRow = .UsedRange.Rows.Count

       For lRow = 2 To lLastRow
           xslProc.addParameter "kunde", CStr(.Cells(lRow, 1).Value)    ' ADD PARAMETER(S)
           xslProc.addParameter "nummer", CStr(.Cells(lRow, 2).Value)
           xslProc.addParameter "dauer", CStr(.Cells(lRow, 3).Value)
           xslProc.addParameter "titel", CStr(.Cells(lRow, 4).Value)
           xslProc.addParameter "system", CStr(.Cells(lRow, 5).Value)
           xslProc.addParameter "datum", CStr(.Cells(lRow, 6).Value)

           xslProc.transform                                            ' TRANSFORM XML
           newDoc.LoadXML xslProc.output                                ' LOAD RESULT TREE
           newDoc.Save "C:\Path\To\Output_" & lRow - 1 & ".xml"         ' SAVE OUTPUT TO FILE
       Next lRow
    End With

    MsgBox "Successfully processed XML files!", vbInformation

ExitHandle:
    Set xmldoc = Nothing: Set newDoc = Nothing
    Set xslDoc = Nothing: Set xslTemp = Nothing: Set xslProc = Nothing
    Exit Sub

ErrHandle:
    MsgBox Err.Number & " - " & Err.Description, vbCritical
    Err.Raise xslDoc.parseError.ErrorCode, , xslDoc.parseError.reason
    Resume ExitHandle
End Sub

实际 XML

请考虑使用此 XSLT,它会调整 &lt;category name="Archivalie_Categories_Attributes:Archivalie"&gt; 下的前 6 个属性/项目节点并保持其他所有内容相同。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:param name="nummer" />
    <xsl:param name="kunde" />
    <xsl:param name="titel" />
    <xsl:param name="datum" />
    <xsl:param name="system" />
    <xsl:param name="dauer" />

    <!-- IDENTITY TRANFORM -->
    <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="category[@name='Archivalie_Categories_Attributes:Archivalie']">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <attribute dateformat="" name="Mandant">
                <item><xsl:value-of select="$nummer"/></item>
            </attribute>
            <attribute dateformat="" name="Bemerkungen zur Stufe">
                <item><xsl:value-of select="$kunde"/></item>
            </attribute>
            <attribute dateformat="" name="Signatur">
                <item><xsl:value-of select="$titel"/></item>
            </attribute>
            <attribute dateformat="" name="Titel">
                <item><xsl:value-of select="$datum"/></item>
            </attribute>
            <attribute dateformat="" name="Bemerkungen">
                <item><xsl:value-of select="$system"/></item>
            </attribute>
            <attribute dateformat="" name="Versicherungswert">
                <item><xsl:value-of select="$dauer"/></item>
            </attribute>
            <xsl:apply-templates select="attribute[position() &gt; 6]|set"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

  • 非常感谢您!与我的示例数据一起工作得很好。星期一再试一次,如果一切正常,会通知你!
  • 哦,已经有一个问题了:假设我的 Input-XML 是我第一篇文章中的复杂文件(以 -tag 开头的那个)。如果我想在这个输入 XML 文件的标签中填充我的参数,我的 XSLT 文件应该是什么样子?我在问,因为此时我不能像目前那样“硬编码” -instructions 周围的标签。我希望你明白我想说什么。如果您可以给我另一个带有原始 XML-Input-file 的示例,那将是最好的,映射的确切标签可以是随机的,它应该只使用原始 XML-Input-file
  • 查看扩展答案,您必须将 XSLT 模板匹配调整为要传递参数并添加身份转换的确切节点。
  • 好的,还有一个我无法处理的错误。我将我的文件复制到这里作为新答案...
猜你喜欢
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-08
  • 2013-09-07
  • 2012-03-30
  • 1970-01-01
相关资源
最近更新 更多