如何从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
代码说明
- 定位Custom XML Part:通过命名空间筛选出目标Custom XML Part,确保后续操作针对正确的数据源。
- 检查XML绑定:利用
ctrl.XMLMapping.IsMapped判断当前ContentControl是否绑定了XML节点。 - 提取属性:通过
boundNode.Attributes遍历绑定节点的所有属性,将属性名和值输出到结果XML中。 - 修正标签格式:原代码中的闭合标签使用
<\xxx>不符合XML规范,改为标准的</xxx>格式。
内容的提问来源于stack exchange,提问作者Dan Ashby
相关产品推荐
相关产品推荐

