有没有办法让Excel在根元素中保留XML属性?

问题描述 投票:7回答:3

我一直在尝试使用MS Excel 2007来编辑存储在XML文件中的表格数据。它可以很好地导入甚至根据模式验证XML数据(xsd文件),但是当我导出时,它会从根元素中删除xmlns,xlmns:xsi和xsi:schemaLocation属性。它还将默认命名空间更改为显式命名空间。

这是一个前/后比较:

之前(导入Excel之前的XML文件)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<database
  xmlns="experimentManager"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="experimentManager Database.xsd">
  <conditionTokens>
    ...
  </conditionTokens>
  <participants>
    ...
  </participants>
</database>

之后(从Excel导出后的XML文件)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:database xmlns:ns1="experimentManager">
    <ns1:conditionTokens>
        ...
    </ns1:conditionTokens>
    <ns1:participants>
        ...
    </ns1:participants>
</ns1:database>

有没有办法阻止Excel剥离这些属性并搞乱命名空间?我已阅读有关XML映射和导入/导出的MS帮助,但GUI中似乎没有任何设置可用于我想要做的事情。如果我需要编写自定义宏,那是可能的,但如果有更好/更简单的方法,我宁愿不这样做。

第二个问题:是否有更好的工具允许使用类似Excel的UI轻松编辑XML文件的某些部分?

xml excel xsd
3个回答
4
投票

好吧,我咬了一口子并写了一个很好的'VBA宏'。我想我会和你们分享,万一其他人遇到同样的问题。

该宏基本上调用Excel的内置XML Export()方法,然后对生成的文件执行一系列文本替换。文本替换完全取决于您。只需将它们放在下面链接中的工作表中即可...

如何设置“替换规则”的示例:Click me for screen cap

在这个例子中,我用空格替换了tab,用空格替换了“:ns1”,用空格替换了“ns1:”,用原始的根元素替换了精简的根元素。

您可以按照自己喜欢的方式格式化替换规则,只要您按照以下说明操作即可:

  1. 选择所有“查找内容”单元格并为其指定名称*“FindWhat”(不要在选择中包含标题行;将忽略空格)。
  2. 选择所有“替换为”单元格并给它们命名*“ReplaceWith”(在“查找内容”和“替换为”单元格之间应该有一对一的映射;使用空格删除不需要的文本)。
  3. 在工作簿中的某处输入XML Map的名称,并将该单元命名为“XmlMap”。
  4. 运行宏。 (系统将要求您指定要导出的文件。)

*如果您不熟悉Excel 2007中的命名范围,请单击“公式”选项卡,然后选择“名称管理器”。

好吧,我不会再让你陷入悬念(LOL)......这里是宏的代码。只需将其放在VBA编辑器的模块中即可。我不保证这个免费代码(如果你没有正确命名范围,你可以很容易地打破它),但我试过的几个例子对我有用。

Option Explicit

Sub ExportXml()
    Dim exportResult As XlXmlExportResult
    Dim exportPath As String
    Dim xmlMap As String
    Dim fileContents As String
    exportPath = RequestExportPath()
    If exportPath = "" Or exportPath = "False" Then Exit Sub
    xmlMap = range("XmlMap")
    exportResult = ActiveWorkbook.XmlMaps(xmlMap).Export(exportPath, True)
    If exportResult = xlXmlExportValidationFailed Then
        Beep
        Exit Sub
    End If
    fileContents = ReadInTextFile(exportPath)
    fileContents = ApplyReplaceRules(fileContents)
    WriteTextToFile exportPath, fileContents
End Sub

Function ApplyReplaceRules(fileContents As String) As String
    Dim replaceWorksheet As Worksheet
    Dim findWhatRange As range
    Dim replaceWithRange As range
    Dim findWhat As String
    Dim replaceWith As String
    Dim cell As Integer
    Set findWhatRange = range("FindWhat")
    Set replaceWithRange = range("ReplaceWith")
    For cell = 1 To findWhatRange.Cells.Count
        findWhat = findWhatRange.Cells(cell)
        If findWhat <> "" Then
            replaceWith = replaceWithRange.Cells(cell)
            fileContents = Replace(fileContents, findWhat, replaceWith)
        End If
    Next cell
    ApplyReplaceRules = fileContents
End Function

Function RequestExportPath() As String
    Dim messageBoxResult As VbMsgBoxResult
    Dim exportPath As String
    Dim message As String
    message = "The file already exists. Do you want to replace it?"
    Do While True
        exportPath = Application.GetSaveAsFilename("", "XML Files (*.xml),*.xml")
        If exportPath = "False" Then Exit Do
        If Not FileExists(exportPath) Then Exit Do
        messageBoxResult = MsgBox(message, vbYesNo, "File Exists")
        If messageBoxResult = vbYes Then Exit Do
    Loop
    RequestExportPath = exportPath
End Function

Function FileExists(path As String) As Boolean
    Dim fileSystemObject
    Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
    FileExists = fileSystemObject.FileExists(path)
End Function

Function ReadInTextFile(path As String) As String
    Dim fileSystemObject
    Dim textStream
    Dim fileContents As String
    Dim line As String
    Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
    Set textStream = fileSystemObject.OpenTextFile(path)
    fileContents = textStream.ReadAll
    textStream.Close
    ReadInTextFile = fileContents
End Function

Sub WriteTextToFile(path As String, fileContents As String)
    Dim fileSystemObject
    Dim textStream
    Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
    Set textStream = fileSystemObject.CreateTextFile(path, True)
    textStream.Write fileContents
    textStream.Close
End Sub

0
投票

实际上,它比那更容易。

  1. .xlsx后缀更改为.zip - xlsx格式实际上是压缩的xml文件!
  2. 在Windows资源管理器中打开zip文件
  3. 浏览到xl子目录
  4. xmlMaps.xml文件复制到.zip文件夹之外的位置
  5. 编辑文件以使用首选命名空间替换nsX:条目并保存更改。
  6. 复制文件并覆盖.zip文件夹中的版本
  7. 将文件夹重命名为.xslx

现在,您的xml映射将显示您首选的命名空间。


0
投票

我尝试了接受的答案,并且喜欢下面的人,我得到了Range全局失败错误,因为让Excel知道XML文件的范围很棘手。然而,我确实为此创建了一种替代方法,我希望我不必这样做,但不幸的是银行系统无法接受带有ns1的XML文件:in。

如果你只是想删除的东西使用下面的文件保存为txt文件,然后在excel中再次打开它,删除ns1:并将其保存为.prn。然后,您只需要将prn更改为xml。

Workbooks.OpenText Filename:= _
    Store & "\" & "\" & sFilename & ".txt", _
    Origin:=xlMSDOS, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _
    xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _
    Comma:=False, Space:=False, Other:=False, FieldInfo:=Array(1, 1), _
    TrailingMinusNumbers:=True
Cells.Replace What:="ns1:", Replacement:="", LookAt:=xlPart, SearchOrder _
    :=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
ActiveWorkbook.SaveAs Filename:= _
    Store & "\" & "\" & sFilename & ".prn", _
    FileFormat:=xlTextPrinter, CreateBackup:=False
ActiveWorkbook.Close savechanges:=False
© www.soinside.com 2019 - 2024. All rights reserved.