Frank C. Rice 和 Paul Cornell
Microsoft Corporation
适用于: Microsoft® Office Word 2003 Beta 2
摘要:在行程中,很多公司的销售代表花费了大量的时间在与客户交谈上。本文探讨一些方法来充分利用 Word 的 XML 功能,使得创建和整理行程报告的过程变得更容易。此外还介绍如何创建 Word 模板,以及如何将数据从一种格式转换为另一种格式。(本文包含一些指向英文站点的链接。)
下载 odc_wdalpine.exe。
本页内容
关于业务
业务问题
解决方案
创建行程报告架构
使用文档模板帮助用户创建 XML 实例文档
将子节点及其子代节点插入到 XML 实例文档中
将 XML 实例文档仅保存为客户定义的 XML 数据
对 XML 实例文档使用转换
小结
关于业务
Alpine Ski House 是美国西海岸的一家户外设备制造商。除了制造雪橇以外,Alpine Ski House 还开始制造滑雪板和滑雪靴。明年,Alpine Ski House 计划增加一条冬季服装生产线。为了准备这个新计划,Alpine Ski House 的 15 名销售代表中的一些已经开始走访美国的各处滑雪胜地,并向滑雪场周围的服装店和礼品店宣传他们的想法。走访期间,销售代表需要在一系列行程报告中记录结果,并每晚将这些报告通过电子邮件发回 Alpine Ski House 总部。Alpine Ski House 的营销小组需要将所有销售代表的行程报告汇总成每日、每周、每月的全面行程报告,并在冬季结束时整理成最终的报告。
业务问题
虽然 Alpine Ski House 的所有销售代表都配有笔记本电脑,而且其中都安装了 Microsoft® Office 2003,但在过去,他们还是需要同时使用 Microsoft Word 文档、电子邮件、Microsoft Excel 电子表格、Microsoft PowerPoint® 演示文稿等来创建行程报告。这使得营销小组需要花费大量的时间来将行程报告中的信息复制并粘贴到汇总报告中。而且,如果行程报告中丢失了关键信息,营销小组还需要与销售代表进行大量后续对话。这对双方来说都需要花费大量时间。
解决方案
推荐的解决方案是必须使用 Word 作为编写行程报告的应用程序。在行程报告中,必须要求销售代表输入营销小组创建汇总报告所需的行程细节。填写行程报告模板的过程不能太繁琐。行程报告必须能够被转换为其他汇总报告格式。最后,如果需要,行程报告中还必须能够灵活地加入一些非营销小组要求的特殊行程细节或其他业务见解。
解决方案由以下组件组成:
行程报告 XML 架构。
行程报告 Word 模板。
营销部用来汇总行程报告的转换。
从操作的角度来看,解决方案必须:
提供文档模板,使用适合的架构并使用需要尽可能少的用户干预的转换。
允许用户将实例文档仅保存为 XML 数据,而不包含任何 Word XML 文档架构标记(虽然保存 XML 数据时可以应用客户定义的转换)。
允许用户通过所需的子代节点,将新的走访报告小节作为现有走访报告小节的子项插入。
允许用户通过所需的子代节点,将新的走访地点报告小节作为现有走访报告小节的子项插入。
允许用户通过所需的子代节点,将新的联系报告小节作为现有联系报告小节的子项插入。
创建行程报告架构
咨询 Alpine Ski House 营销部后,确定了销售人员需要收集以下信息来填写营销数据库。
销售人员的姓名和电子邮件地址。
进行走访的日期。
包含该日期进行的所有走访的常规汇总。
对于每个走访的地理区域,都要有一个全面的走访汇总并记录该区域中走访过的地点,包括地点名称、地点摘要、地点地址以及每个地点的联系人。
对于每位联系人,都要记录姓名、电子邮件地址、街道地址、电话号码、传真号码、移动电话号码、寻呼机号码、其他联系方式、走访开始和结束时间以及与联系人有关的任何其他注释信息。
基于此信息创建了以下客户定义的架构:
<?xml version="1.0" encoding="utf-8" ?> <xs:schema targetNamespace= "http://www.alpineskihouse.com/schemas/tripReports/salespeople" elementFormDefault="qualified" xmlns= "http://www.alpineskihouse.com/schemas/tripReports/salespeople" xmlns:mstns= "http://www.alpineskihouse.com/schemas/tripReports/salespeople" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="placeContact_type"> <xs:annotation> <xs:documentation>If you visit multiple people at a location you can record a separate contact for each person visited. </xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="placeContactName" type="xs:string" /> <xs:element name="placeContactEmail" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactAddress" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactOfficePhone" type="telephone_type" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactOfficeFax" type="telephone_type" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactMobilePhone" type="telephone_type" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactPager" type="telephone_type" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactOtherCommunication" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactStartTime" type="xs:time" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactEndTime" type="xs:time" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactNotes" type="xs:string" minOccurs="0" maxOccurs="1" /> </xs:sequence> </xs:complexType> <xs:complexType name="placeContacts_type"> <xs:sequence> <xs:element name="placeContact" type="placeContact_type" minOccurs="1" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:complexType name="visitedPlace_type"> <xs:sequence> <xs:element name="placeName" type="xs:string" /> <xs:element name="placeAddress" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="placeSummary" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContacts" type="placeContacts_type" minOccurs="0" maxOccurs="1" /> </xs:sequence> </xs:complexType> <xs:complexType name="visitedPlaces_type"> <xs:sequence> <xs:element name="visitedPlace" type="visitedPlace_type" minOccurs="1" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:complexType name="visit_type"> <xs:sequence> <xs:element name="visitLocation" type="xs:string" /> <xs:element name="visitSummary" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="visitedPlaces" type="visitedPlaces_type" minOccurs="0" maxOccurs="1"> <xs:annotation> <xs:documentation>You can break individual visits up into multiple "visitedPlaces" elements if needed.</xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="tripReport_type"> <xs:sequence> <xs:element name="salespersonName" type="xs:string" /> <xs:element name="salespersonEmail" type="xs:string" /> <xs:element name="reportDate" type="xs:date" /> <xs:element name="reportSummary" type="xs:string" minOccurs="0" maxOccurs="1"> <xs:annotation> <xs:documentation>A summary of all of the day's reports.</xs:documentation> </xs:annotation> </xs:element> <xs:element name="visits" type="visits_type" minOccurs="0" maxOccurs="1"> <xs:annotation> <xs:documentation>You can break the day's visits up into multiple "visit" elements if needed.</xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="visits_type"> <xs:sequence> <xs:element name="visit" type="visit_type" minOccurs="1" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:element name="tripReport" type="tripReport_type"> <xs:annotation> <xs:documentation>Defines an Alpine Ski House trip report.</xs:documentation> </xs:annotation> </xs:element> <xs:simpleType name="telephone_type"> <xs:annotation> <xs:documentation>Accepts United States phone number patterns only.</xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:pattern value="([0-9][0-9][0-9]) [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]" /> </xs:restriction> </xs:simpleType> </xs:schema>
该架构遵循以下基本模式:
<tripReport> <salespersonName> <salespersonEmail> <reportDate> <reportSummary> <visits> <visit> <visitLocation> <visitSummary> <visitedPlaces> <visitedPlace> <placeName> <placeAddress> <placeSummary> <placeContacts> <placeContact> <placeContactName> <placeContactEmail> <placeContactAddress> <placeContactOfficePhone> <placeContactOfficeFax> <placeContactMobilePhone> <placeContactPager> <placeContactOtherCommunication> <placeContactStartTime> <placeContactEndTime> <placeContactNotes>
一些主要架构设计决策包括以下内容:
定义可扩展命名空间。当 W3C XML Schema 建议处于初始阶段时,组织会创建一些看起来比较奇怪的命名空间,这些命名空间似乎不遵循任何模式,例如 uri:schemas-myCompany-com#mySchema、schemas.myCompany.com.mySchema 等。按照惯例,鼓励组织使用自己的 Internet URL,其后采用内部统一的命名规则。命名空间看起来应与 Internet 地址非常类似。例如,Alpine Ski House 使用 http://www.alpineskihouse.com/schemas 作为其基本命名空间,后面是架构用途,再后面是将主要使用此架构的小组。按照此命名规则,Alpine Ski House 可以创建以下架构名称:
使用单个元素组件定义根元素,使用一系列 complexType 组件来定义所有根元素的子代元素。例如,在 tripReport_type 类型的 tripReport 元素组件中定义根元素,如下所示:...
<xs:element name="tripReport" type="tripReport_type" /> ... tripReport_type 被定义为 complexType 组件,如下所示: <xs:complexType name="tripReport_type"> <xs:sequence> <xs:element name="salespersonName" type="xs:string" /> <xs:element name="salespersonEmail" type="xs:string" /> <xs:element name="reportDate" type="xs:date" /> <xs:element name="reportSummary" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="visits" type="visits_type" minOccurs="0" maxOccurs="1" /> </xs:sequence> </xs:complexType>
...visits_type 再在另一个 complexType 组件中进行定义,依次进行下去。并决定将 suffix _type 添加到 simpleType 和 complexType 组件名称中,以便更容易地从元素名称定义中区分出类型名称定义。
将文档直接嵌入到架构中。每个组件允许包含一个子批注元素,子批注元素又允许包含一个子文档元素,子文档元素可以包含文档,例如:...
<xs:element name="tripReport" type="tripReport_type"> <xs:annotation> <xs:documentation>Defines an Alpine Ski House trip report.</xs:documentation> </xs:annotation> </xs:element>
如果可能,请使用 minOccurs 和 maxOccurs 属性来严格定义组件出现的次数。
如果可能,请使用严格数据键入以利用应用程序的内置架构验证功能。
如果可能,请限制输入值的范围以利用应用程序的内置数据输入验证功能。
<xs:complexType name="placeContact_type"> <xs:annotation> <xs:documentation>If you visit multiple people at a location you can record a separate contact for each person visited. </xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="placeContactName" type="xs:string" /> <xs:element name="placeContactEmail" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactAddress" type="xs:string" minOccurs="0" maxOccurs="1" /> <xs:element name="placeContactOfficePhone" type="telephone_type" minOccurs="0" maxOccurs="1" /> ... ... <xs:simpleType name="telephone_type"> <xs:annotation> <xs:documentation>Accepts United States phone number patterns only.</xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> <xs:pattern value="([0-9][0-9][0-9]) [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]" /> </xs:restriction> </xs:simpleType> </xs:schema>
行程报告架构是使用 Microsoft Visual Studio® .NET 创建的,步骤如下:
启动 Visual Studio .NET。
在 File(文件)菜单中,指向 New(新建),并单击 File(文件)。
在 New File(新建文件)对话框中,打开左侧窗格中的 General(常规)文件夹,然后单击右侧窗格中的 XML Schema(XML 架构)图标,并单击 Open(打开)。
在 View(视图)菜单中,单击 Toolbox(工具箱)。
将架构组件(元素、属性、简单类型和复杂类型、面等)拖到可视化设计器中。
使用可视化设计器自定义架构组件。
可以单击 View(视图)菜单中的 XML Source(XML 源)进一步优化架构。
创建完架构后,单击 File(文件)菜单中的 Save(保存),将 .xsd 文件保存到所需的位置。
有关使用架构语法的帮助,请在架构视图或 XML 视图中的任意架构组件内部单击,然后在 Help(帮助)菜单中单击 Dynamic Help(动态帮助)。
要在 Visual Studio .NET 中查看行程报告架构:
启动 Visual Studio .NET。
在 File(文件)菜单中,指向 Open(打开),并单击 File(文件)。
找到并单击 trip_report_sales.xsd 文件,然后单击 Open(打开)。
使用文档模板帮助用户创建 XML 实例文档
为了帮助用户创建 XML 实例文档,所有文档模板都用颜色、阴影、文本格式等从视觉方面进行加强。用户在保存 XML 实例文档时可以不包含可视化格式细节,在保存的 XML 实例文档中不改变客户定义的 XML 数据。
要使用嵌入的、客户定义的 XML 来创建文档模板:
启动 Word。将显示一个空白的新文档。
在 Tools(工具)菜单中,单击 Templates And Add-Ins(模板和加载项)。
如果显示有“http://www.alpineskihouse.com/schemas/tripReports/salespeople”复选框,请选中此框,并单击 OK(确定)。
如果未显示“http://www.alpineskihouse.com/schemas/tripReports/salespeople”复选框:在 XML Schema(XML 架构)选项卡中,单击 Schema Library(架构库)。
单击 Add Schema(添加架构)。
找到并单击 trip_report_sales.xsd 文件(包含在本文的下载程序中),并单击 Open(打开)。
依次单击两个对话框中的 OK(确定)。
选中“http://www.alpineskihouse.com/schemas/tripReports/salespeople”复选框,并单击 OK(确定)。
附加了行程报告架构以后:
为文档添加文本、格式、颜色等。
使用 XML Structure(XML 结构)任务窗格将元素添加到文档。
将文件保存为 Word 文档模板 (.dot)。
注意:如果希望用户可以创建有效的 XML 文档,而不考虑模板中 XML 组件内的任何文本格式,请在保存文档模板之前,单击 XML Structure(XML 结构)任务窗格中的 XML Options(XML 选项),并选中 Ignore Mixed Content(忽略混合的内容)复选框,然后单击 OK(确定)。如果用户仅保存 XML 文档的 XML 数据,则保存 XML 文档时不会保存文本格式以及嵌入式元素以外的任何其他内容。如果用户将 XML 文档保存为 Word XML 文档架构格式,则保存 XML 文档时会同时保存嵌入元素和文本格式。
要查看行程报告文档模板的已完成版本,请使用 Word 打开 TripReportTemplate.dot 文件(包含在本文的下载程序中)。
图 1:TripReportTemplate.dot 文件
将子节点及其子代节点插入到 XML 实例文档中
为了插入子节点及其子代节点,文档模板附加了 Microsoft Basic® for Applications (VBA) 代码。装入文档模板后,就会创建一个带有多个命令的自定义工具栏,来插入子节点及其可视子代节点(请参阅图 2)。
图 2:自定义工具栏
只有当用户的插入点位于某个节点中时,这些命令才可用,这样,用户就不可能在文档的错误位置误插入节点。为了保持简洁,关闭文档模板后,将删除这个相关联的工具栏。
VBA 代码如下:
Public WithEvents gwdApp As Word.Application Private Const TOOLBAR_NAME = "Trip Report Actions" Public gcbToolbar As Office.CommandBar Dim wdApp As New DeclareWordApp Public Sub CreateToolbar() Dim cbToolbar As Office.CommandBar Dim blnToolbarExists As Boolean Dim strCaptions(1 To 4) As String Dim strOnActions(1 To 4) As String blnToolbarExists = False ' 如果工具栏存在,请勿创建重复的工具栏。 For Each cbToolbar In Application.CommandBars If cbToolbar.Name = TOOLBAR_NAME Then blnToolbarExists = True End If Next cbToolbar If blnToolbarExists = False Then Set gcbToolbar = Application.CommandBars.Add(TOOLBAR_NAME) strCaptions(1) = "New Visit" strOnActions(1) = "InsertItem.InsertNewVisit" strCaptions(2) = "New Place" strOnActions(2) = "InsertItem.InsertNewPlace" strCaptions(3) = "New Contact" strOnActions(3) = "InsertItem.InsertNewContact" strCaptions(4) = "Save As XML" strOnActions(4) = "SaveDoc.SaveDocAsXML" Call AddButtons(gcbToolbar, 4, strCaptions, strOnActions) gcbToolbar.Visible = True End If End Sub Public Sub DeleteToolbar() Dim cbToolbar As Office.CommandBar For Each cbToolbar In Application.CommandBars If cbToolbar.Name = TOOLBAR_NAME Then cbToolbar.Delete End If Next cbToolbar End Sub Private Function AddButtons(ByRef cbToolbar As Office.CommandBar, _ ByVal intNumButtons As Integer, ByRef strCaptions() As String, _ ByRef strOnActions() As String) As Office.CommandBar Dim cbToolbarButton As Office.CommandBarButton Dim intCounter As Integer intCounter = 1 Do While intCounter <= intNumButtons Set cbToolbarButton = cbToolbar.Controls.Add(msoControlButton) With cbToolbarButton .Style = msoButtonCaption .Caption = strCaptions(intCounter) .OnAction = strOnActions(intCounter) .Enabled = True End With intCounter = intCounter + 1 Loop Set AddButtons = cbToolbar End Function Private Sub Document_Open() Set gwdApp = Word.Application Call CreateToolbar End Sub Private Sub Document_Close() Call Toolbar.DeleteToolbar Set wdApp = Nothing End Sub Public Sub InsertNewVisit() On Error Resume Next Call InsertNewVisitHandler2(Selection.XMLParentNode) End Sub Public Sub InsertNewPlace() On Error Resume Next Call InsertNewPlaceHandler2(Selection.XMLParentNode) End Sub Public Sub InsertNewContact() On Error Resume Next Call InsertNewContactHandler2(Selection.XMLParentNode) End Sub Public Sub InsertNewVisitHandler2(ByRef objNode As Word.XMLNode) On Error Resume Next Dim objVisitedPlacesNode As Word.XMLNode Dim objVisitedPlaceNode As Word.XMLNode Dim objPlaceContactNode As Word.XMLNode If objNode.BaseName = "visits" Then Dim objPlaceNode As Word.XMLNode objNode.ChildNodeSuggestions(1).Insert ' visit objNode.ChildNodes(1).ChildNodeSuggestions(1).Insert ' visitLocation Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(2).Insert ' visitSummary Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(3).Insert ' visitedPlaces Set objVisitedPlacesNode = objNode.ChildNodes(1).ChildNodes(3) ' visitedPlaces Set objVisitedPlaceNode = InsertNewPlaceHandler2(objVisitedPlacesNode) Set objPlaceContactNode = InsertNewContactHandler2(objVisitedPlaceNode) Else MsgBox "You must click inside of a visits element first." End If End Sub Public Function InsertNewPlaceHandler2(ByRef objNode As Word.XMLNode) As Word.XMLNode On Error Resume Next If objNode.BaseName = "visitedPlaces" Then Dim objContactsNode As Word.XMLNode Dim objContactNode As Word.XMLNode objNode.ChildNodeSuggestions(1).Insert ' visitedPlace objNode.ChildNodes(1).ChildNodeSuggestions(1).Insert ' placeName Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(2).Insert ' placeAddress Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(3).Insert ' placeSummary Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(4).Insert ' placeContacts Set objContactsNode = objNode.ChildNodes(1).ChildNodes(4) ' placeContacts Set objPlaceContactNode = InsertNewContactHandler2(objContactsNode) Else MsgBox "You must click inside of a visitPlaces element first." End If End Function Public Function InsertNewContactHandler2(ByRef objNode As Word.XMLNode) As Word.XMLNode On Error Resume Next If objNode.BaseName = "placeContacts" Then objNode.ChildNodeSuggestions(1).Insert ' placeContact objNode.ChildNodes(1).ChildNodeSuggestions(1).Insert ' placeContactName Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(2).Insert ' placeContactEmail Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(3).Insert ' placeContactAddress Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(4).Insert ' placeContactOfficePhone Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(5).Insert ' placeContactOfficeFax Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(6).Insert ' placeContactMobilePhone Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(7).Insert ' placeContactPager Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(8).Insert ' placeContactOtherCommunication Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(9).Insert ' placeContactStartTime Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(10).Insert ' placeContactEndTime Selection.MoveRight objNode.ChildNodes(1).ChildNodeSuggestions(11).Insert ' placeContactNotes Else MsgBox "You must click inside of a placeContacts element first." End If End Function
将 XML 实例文档仅保存为客户定义的 XML 数据
用户需要将实例文档仅保存为客户定义的 XML 数据而不包含任何 Word XML 文档架构标记,为了满足这一需求,文档模板附加了 VBA 代码。使用该代码,用户可以非常容易地在文档模板处于活动状态时保存客户定义的 XML 数据。
VBA 代码如下:
Public Sub SaveDocAsXML() On Error GoTo SaveDocAsXML_Err ActiveDocument.XMLSaveDataOnly = True ActiveDocument.SaveAs , wdFormatXML SaveDocAsXML_End: Exit Sub SaveDocAsXML_Err: Select Case Err.Number Case 6119 ' XML 无效。 MsgBox Err.Description & ". Please correct the " & _ "document and try again." GoTo SaveDocAsXML_End Case Else MsgBox Err.Number & " " & Err.Description GoTo SaveDocAsXML_End End Select End Sub
对 XML 实例文档使用转换
当营销部向 Alpine Ski House 董事会报告结果时,只希望包含以下信息:
进行走访的销售人员姓名和走访日期。
所有走访的全面汇总
全面走访汇总中已走访的地理区域。
每个地理区域中的位置名称和位置摘要。
每个走访位置的联系人姓名和联系人注释。
可以对 TripReportTemplate.dot 运行以下 XSL 文件,以创建仅包含以上信息的 XML 文件。将以下内容复制成一个具有 .xsl 扩展名的文件:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sr="http://www.alpineskihouse.com/schemas/" & _ "tripReports/salespeople" xmlns:mr="http://www.alpineskihouse.com/" & _ "schemas/tripReports/marketing"> <xsl:template match="/sr:tripReport"> <mr:tripReport> <xsl:apply-templates/> </mr:tripReport> </xsl:template> <xsl:template match="sr:salespersonName"> <mr:salesperson> <xsl:value-of select="."/> </mr:salesperson> </xsl:template> <xsl:template match="sr:salespersonEmail"/> <xsl:template match="sr:reportDate"> <mr:date> <xsl:value-of select="."/> </mr:date> </xsl:template> <xsl:template match="sr:reportSummary"> <mr:summary> <xsl:value-of select="."/> </mr:summary> </xsl:template> <xsl:template match="sr:visits"> <mr:visits> <xsl:for-each select="./sr:visit"> <mr:visit> <mr:location> <xsl:value-of select="./sr:visitLocation"/> </mr:location> <mr:summary> <xsl:value-of select="./sr:visitSummary"/> </mr:summary> <mr:places> <xsl:apply-templates select= & _ "./sr:visitedPlaces"/> </mr:places> </mr:visit> </xsl:for-each> </mr:visits> </xsl:template> <xsl:template match="sr:visitedPlaces"> <xsl:for-each select="./sr:visitedPlace"> <mr:place> <xsl:apply-templates/> </mr:place> </xsl:for-each> </xsl:template> <xsl:template match="sr:placeName"> <mr:name> <xsl:value-of select="."/> </mr:name> </xsl:template> <xsl:template match="sr:placeAddress"/> <xsl:template match="sr:placeSummary"> <mr:summary> <xsl:value-of select="."/> </mr:summary> </xsl:template> <xsl:template match="sr:placeContacts"> <mr:contacts> <xsl:for-each select="./sr:placeContact"> <mr:contact> <xsl:apply-templates/> </mr:contact> </xsl:for-each> </mr:contacts> </xsl:template> <xsl:template match="sr:placeContactName"> <mr:name> <xsl:value-of select="."/> </mr:name> </xsl:template> <xsl:template match="sr:placeContactEmail"/> <xsl:template match="sr:placeContactAddress"/> <xsl:template match="sr:placeContactOfficePhone"/> <xsl:template match="sr:placeContactOfficeFax"/> <xsl:template match="sr:placeContactMobilePhone"/> <xsl:template match="sr:placeContactPager"/> <xsl:template match="sr:placeContactOtherCommunication"/> <xsl:template match="sr:placeContactStartTime"/> <xsl:template match="sr:placeContactEndTime"/> <xsl:template match="sr:placeContactNotes"> <mr:notes> <xsl:value-of select="."/> </mr:notes> </xsl:template> </xsl:stylesheet>
可以使用转换来更改 XML 文档的实际内容。将 XML 文档打开,当单击 File(文件)菜单上的 Save As(另存为)时,选中 Apply Transform(应用转换)复选框,单击 Transform(转换),选择一种转换,单击 Open(打开),然后单击 Save(保存)。当保存 XML 文档时,将对 XML 文档的内容应用此转换。
小结
本文通过一家虚拟公司 Alpine Ski House 说明了如何使用 Word 的 XML 功能来创建一个系统,帮助公司的销售代表记录、归档和转换走访行程中获得的信息。应用程序使用了 XML 模板。在该模板中,销售代表将数据输入到预先格式化的字段中。然后将这些数据仅保存为 XML 数据;或者在保存时进行转换,将数据转换为汇总格式。销售代表还可以根据需要使用自定义工具栏轻松地将附加元素添加到模板。使用 Word 和其他 Microsoft Office 应用程序中的类似功能,可以减少零散组合在一起的多个传统系统中常见的操作和重复内容。