【问题标题】:Is there any way to make Excel preserve XML attributes in root element?有没有办法让 Excel 在根元素中保留 XML 属性?
【发布时间】:2009-06-28 20:57:48
【问题描述】:

我一直在尝试使用 MS Excel 2007 来编辑存储在 XML 文件中的表格数据。它在导入甚至针对模式(xsd 文件)验证 XML 数据方面做得很好,但是当我导出时,它会从根元素中删除 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 文件的某些部分?

【问题讨论】:

  • 请注意,Excel 不会更改命名空间。它只是删除xsi:schemaLocation,然后删除未使用的xsi 命名空间。

标签: xml excel xsd


【解决方案1】:

好吧,我硬着头皮写了一个不错的 VBA 宏。我想我会与大家分享,以防其他人遇到同样的问题。

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

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

在此示例中,我将 tab 替换为空格,将 ":ns1" 替换为空白,将 "ns1:" 替换为空白,并将精简后的根元素替换为原始根元素。

您可以按照自己喜欢的方式设置替换规则的格式,只要您遵循以下说明:

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

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

好的,我不会再让你陷入悬念了(哈哈)...这是宏的代码。只需将其放在 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

【讨论】:

  • 宏的运行以runtime error 1004, Methode "Range" for the object "Global" failed 结束。我做错了什么?
【解决方案2】:

其实比这简单很多。

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

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

【讨论】:

    【解决方案3】:

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

    如果您只想删除某些内容,请使用以下命令将文件另存为 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-06
      • 1970-01-01
      • 2021-07-25
      • 2015-04-10
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      • 1970-01-01
      相关资源
      最近更新 更多