You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Word的ContentControl中提取CustomXMLPart数据?

问题描述

我有一份由Word文档另存生成的完整XML文件,其中Word里的ContentControl对应的topic在XML中带有如下属性标签:

<pkg:part pkg:name="/customXml/item9.xml" ....>
<pkg:xmlData>
<er:document ....>
...
<er:heading sdt-id="398909766" title="SUBPART A – GENERAL"/>
<er:toc>
<er:topic sdt-id="-367401465" source-title="CS 25.1 Applicability"
 ERulesId="ERULES-1963177438-9651"   Domain="Initial airworthiness;"
 ActivityType="" AircraftUse="" AircraftCategory="" AmendedBy="Amendment 11;" 
 ApplicabilityDate="4 July, 2011" EntryIntoForceDate="4 July, 2011"
 EquivalentForeignRegulation="" ICAOReference="" Keywords=""
 RegistryState="" RegulatedEntity="" RegulatorySource="ED Decision 2011/004/R"
 RegulatorySubject="CS-25;" TechnicalSubjectMatter="" TypeOfContent="CS (Certification specification);" 
ParentIR="" EASACategory=""/>
</er:toc>               

这些标签和Word的XML映射窗格中的Custom XML Part匹配。我现有一段VBA代码可以提取ContentControl的文本,但无法获取Custom XML Part里的这些属性标签。查了很多资料大多是关于添加或删除Custom XML Part内容的,没找到提取属性的方法,求技术帮助。

现有VBA代码:

Sub ExtractTopic()
'
' ExtractTopic Macro
'
'
    Dim ctrl As ContentControl
    Dim xml As CustomXMLPart
    
    Dim Path As String
    Dim FileNumber As Integer
    Dim FirstHeading As Boolean
    
    Path = ActiveDocument.Path & Application.PathSeparator & "TestOutput.xml"
    FileNumber = FreeFile
    
    Open Path For Output As #FileNumber
    
    FirstHeading = True
    Print #FileNumber, "<ctrls>"
    
    For Each xml In ActiveDocument.CustomXMLParts
        If InStr(xml.NamespaceURI, "easa") Then
            Exit For
        End If
    Next xml
    
    For Each ctrl In ActiveDocument.ContentControls
        Select Case ctrl.Title
            Case "heading"
                If Not FirstHeading Then
                   Print #FileNumber, "<\heading>"
                End If
                Print #FileNumber, "<heading>"
                Print #FileNumber, ctrl.Range.Text
            Case "topic"
                Print #FileNumber, "<topic>"
                Print #FileNumber, "<id=" & ctrl.ID & "\>"
                Print #FileNumber, "<text>"
                Print #FileNumber, ctrl.Range.Text
                Print #FileNumber, "<\text>"
                Print #FileNumber, "<\topic>"
            Case Else
                Print #FileNumber, "<" & ctrl.Title & ">"
                Print #FileNumber, "<\" & ctrl.Title & ">"
        End Select
        
    Next ctrl
    
    Print #FileNumber, "<\heading>"
    Print #FileNumber, "<\ctrls>"
    
    Close FileNumber
End Sub
解决方案

要提取Custom XML Part中绑定到ContentControl的节点属性,核心是利用ContentControl.XMLMapping对象找到对应的CustomXMLNode,然后遍历该节点的属性集合。

修改后的VBA代码如下:

Sub ExtractTopicWithXMLAttributes()
    Dim ctrl As ContentControl
    Dim targetXMLPart As CustomXMLPart
    Dim boundNode As CustomXMLNode
    Dim attr As CustomXMLAttribute
    Dim Path As String
    Dim FileNumber As Integer
    Dim FirstHeading As Boolean
    
    ' 输出文件路径
    Path = ActiveDocument.Path & Application.PathSeparator & "TestOutput_WithAttributes.xml"
    FileNumber = FreeFile
    
    Open Path For Output As #FileNumber
    
    FirstHeading = True
    Print #FileNumber, "<ctrls>"
    
    ' 定位目标Custom XML Part(根据命名空间筛选)
    For Each targetXMLPart In ActiveDocument.CustomXMLParts
        If InStr(targetXMLPart.NamespaceURI, "easa") Then
            Exit For
        End If
    Next targetXMLPart
    
    ' 遍历所有ContentControl
    For Each ctrl In ActiveDocument.ContentControls
        Select Case ctrl.Title
            Case "heading"
                If Not FirstHeading Then
                   Print #FileNumber, "</heading>"
                End If
                Print #FileNumber, "<heading>"
                Print #FileNumber, ctrl.Range.Text
                FirstHeading = False
            Case "topic"
                Print #FileNumber, "<topic id='" & ctrl.ID & "'>"
                Print #FileNumber, "  <text>" & ctrl.Range.Text & "</text>"
                
                ' 检查当前ContentControl是否绑定了XML节点
                If ctrl.XMLMapping.IsMapped Then
                    Set boundNode = ctrl.XMLMapping.Node
                    If Not boundNode Is Nothing Then
                        Print #FileNumber, "  <attributes>"
                        ' 遍历节点的所有属性并输出
                        For Each attr In boundNode.Attributes
                            Print #FileNumber, "    <" & attr.BaseName & ">" & attr.Text & "</" & attr.BaseName & ">"
                        Next attr
                        Print #FileNumber, "  </attributes>"
                    End If
                End If
                
                Print #FileNumber, "</topic>"
            Case Else
                Print #FileNumber, "<" & ctrl.Title & ">" & ctrl.Range.Text & "</" & ctrl.Title & ">"
        End Select
    Next ctrl
    
    ' 闭合标签
    If Not FirstHeading Then
        Print #FileNumber, "</heading>"
    End If
    Print #FileNumber, "</ctrls>"
    
    Close FileNumber
    MsgBox "提取完成,文件已保存至:" & Path, vbInformation
End Sub

代码说明

  1. 定位Custom XML Part:通过命名空间筛选出目标Custom XML Part,确保后续操作针对正确的数据源。
  2. 检查XML绑定:利用ctrl.XMLMapping.IsMapped判断当前ContentControl是否绑定了XML节点。
  3. 提取属性:通过boundNode.Attributes遍历绑定节点的所有属性,将属性名和值输出到结果XML中。
  4. 修正标签格式:原代码中的闭合标签使用<\xxx>不符合XML规范,改为标准的</xxx>格式。

内容的提问来源于stack exchange,提问作者Dan Ashby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 12:30:52