内容


WebSphere Integration Developer V7 中的 XML 映射,第 1 部分

使用 Mapping Editor 开发映射

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: WebSphere Integration Developer V7 中的 XML 映射,第 1 部分

敬请期待该系列的后续内容。

此内容是该系列的一部分:WebSphere Integration Developer V7 中的 XML 映射,第 1 部分

敬请期待该系列的后续内容。

简介

XML 映射用于将源 XML 文档转换为一个目标 XML 文档。映射编辑器获取 Mapping Editor 中创建的映射并生成一个 XSL 文件,以在运行时执行实际的 XML 转换。在 WebSphere Integration Developer 中,XML 映射主要用于以下两种情况:

  • 在构建中介流时,在一些实例中,来自某个原语的输出消息结构无法与下一个原语的输入消息结构匹配。消息作为 Service Message Objects (SMO) 通过中介流,SMO 具有一个一致的 XML 结构。这种情况下,您可以使用一个映射来将消息从一种结构转换为另一种结构。
  • 在构建一个处理流时,也会遇到处理流中的某个变量需要转换类型的情况。可以在处理流中使用 XML 映射来转换和操作变量。

在创建映射时,其目的是构建一个将生成完整、有效的目标 XML 文档的映射。生成的 XML 文档需要保持完整,因为它包含所有需要的数据,并且该文档必须是有效的并匹配对应的模式。

本系列的第 2 部分 处理复杂的 XML 结构 解释了更多高级的 XML 映射主题。

Mapping Editor

Mapping Editor 使得用源 XML 文档的数据填充目标 XML 文档变得非常的简单和直观。一般而言,源 XML 结构显示在编辑器的左侧,而目标 XML 结构显示在右侧,如 图 1 所示。通过在源字段和目标字段之间建立连接,您将在源元素和属性与目标元素和属性之间建立映射。编辑区下的属性视图允许您细分和定制在 Mapping Editor 中创建的映射。Mapping Editor 还包含了一个测试视图,允许您关联样例输入 XML 并立即查看映射的 XML 输出。

图 1. XML Mapping Editor
XML Mapping Editor
XML Mapping Editor

创建映射

在哪里创建映射

映射通常在 Mediation Module 项目内创建,以用于某个特定的 Mediation Flow 或 Module 项目内,供某个 Business Process 流使用。也可以在 Library 项目内创建,这将使它们可以重用于任何位于模块中的映射文件。这个模块必须独立于 Library。

在 Mediation Flow 内,映射文件通过 XSL Transformation 原语创建。每个 XSL Transformation 原语都与一个映射文件相关联,该文件描述将对输入 XML 进行的转换。映射文件是根据在实现原语时指定的信息创建的。

在 Business Process Flow 内,映射文件通过 Data Map 基本操作创建。

在处理映射时,您可能发现您总是会不断映射相同的两个元素类型。这种情况下,创建一个 Submap 会很有用,它可以在映射到这两个类型时得到重用。一个 Submap 就是指一个常规的映射文件,您可以使用 Submap 转换从其他映射文件中调用。可以从 Mapping editor 中创建一个 Submap,或者通过右键单击 Business Integration 视图并选择 New > XML Map 来创建。

选择一个映射根

映射根就是指映射内的根级别的输入和输出对。一般来讲,输入基于一种 XML Schema 类型,而输出基于其他一些 XML Schema 类型。

在 Mediation Flow 内创建映射时,需要一个映射根。映射根确定原语输入消息的哪个部分被用作映射输入,以及原语输出消息的哪个部分用作映射输出。要选择映射根,首先确定需要对目标文档的哪个部分做修改,然后确定从哪里获得用于填充目标文档的数据。 一旦确定了将要处理的文档区域,可以为映射选择适当的根。在中介流中使用的 XML 映射只能有一个单一的输入或源以及一个单一的输出或目标。对于中介流,使用被分解为以下几个部分的 SMO 消息:

  • 上下文
  • 标题
  • 消息体

可以选择 SOM 的某个部分作为根,或者选择 SMO 的根,如果需要多个部分的话。大多数情况下,修改通常会发生 SMO 消息体,而消息体则适合做映射的根。然而,有些时候,您可能需要来自上下文或标题的数据填充目标消息体。另外一些情况下,可能需要更新目标上下文或目标标题。在这些情况下,将需要使用 SOM 的根 “/” 作为映射根。使用 “/” 作为根允许您访问源和目标 SMO 的所有部分。一旦使用选择的根创建了 SMO 映射,您就再也无法修改根了。

映射细分

在使用 Mapping Editor 时,将把源模式的元素和属性与目标模式的元素和属性关联起来。在源和目标之间建立好关联后,这种关联被称为转换或映射。每个映射可以有一个细分(refinement),以表示映射的类型。本节将描述这种细分。

Move

Move 是最基本的细分。它在源端有一个简单或复杂的字段,然后不加修改地将该字段从源移动到目标。对复制的字段进行的惟一修改就是对名称空间前缀的修改,以确保它们在目标文档的有效性。当希望将一些内容原封不动地从源复制到目标时,推荐使用 Move 细分。

Convert

New icon Convert 细分用于对简单数据类型执行一些简单的转换。Convert 细分的一个用例就是将 Boolean 值(真或假)转换为 Int 值(1 或 0)。另一个用例是从字符串中提取特定类型的值。例如,考虑某个人的年龄,一个业务对象可能会将年龄表示为一个字符串,而另一个业务对象则会表示为一个整数值。对于这种情况,您可以使用 Convert 来确保字符串格式的年龄(预期的值,但不一定要为整数值)在目标中为一个整数值。对于不能将字符串转换为整数的情况,将在目标字段中使用一个用户指定的默认整数。

Assign

Assign 细分用于希望将一个常量值指定给一个目标元素或属性时。Assign 只能用于为简单类型字段指定值,比如字符串和整数。要创建 Assign 映射:

  1. 选择目标元素或属性以指定值。
  2. 右键单击目标元素或属性并选择 Create Transform
  3. 使用 Properties 视图,向目标元素或属性指定合适的值。

Local map

Local map 是一种用于组织映射文件的工具。它允许您为复杂类型嵌套映射,这样顶级映射就不会因为大量的细节变得散乱。需要意识到一点,在源和目标之间创建 Local map 本身不会执行任何数据转换。不会从源向目标移动内容,直到您进入 Local map 并使用 Move 之类的细分创建映射。Local map 被用作一个容器映射来本地化嵌套映射(比如 Move),这将执行实际的转换。

一个 Local map 包含一个单独的输入字段和一个单独的输出字段。对于需要多个输入字段的情况下,一个 Merge 映射将替代 Local 映射,但是其行为是类似的。

在源和目标之间创建了 Local map 后,可以双击 Local map 细分以进入该映射。进入 Local map 后,您可以创建子映射。在 Local map 内,您将注意到可以导航到 Local map 以外,通过使用映射区域右上角的 “Up a level” 图标(Up a level icon)回到父映射。在 Local map 内部时,您会注意到使用了一个灰色背景来表示您正在某个嵌套映射内。

Local map 是不可重用的。如果正在映射的源和目标类型将要以与其他映射相同的方式进行映射,那么考虑使用一个可重用且可在多个映射文件之间共享的 Submap。参见本文的 Submap 部分,了解创建 Submaps 的更多信息。

Merge

Merge 细分类似于 Local map,因为它是一个用于嵌套其他映射的容器。与 Local 不同,Merge 支持多个源输入。这允许您从两个不同的源字段获取数据并将它们合并到一个目标字段中。Merge 也用于处理数组。有关更多信息,请参见第 2 部分的 使用数组

Submap

Submap 细分是指存储在不同文件中的两个特定类型之间的映射。一个 Submap 就是指一个常规 map 文件中的根映射,您可以从任何其他 map 文件中引用它,因此非常适合重用。由于 Submaps 专门针对重用,因此我们建议您将 Submaps 存储在库中,在其中可以在独立模块之间轻松地共享和重用 Submap。如果有两个不同的复杂类型,并且这两个类型在映射时关系非常紧密,那么 Submap 是在这两种类型之间创建可重用映射的好方法。

New icon 如果已经创建了一个 local map 并且决定让这个 local map 能够多次使用,那么可以将 local map 的内容重构到一个 submap 中。要执行这个操作,可以右键单击 local map 并选择 Refactor to Submap

某些情况下,您会发现无法为一个需要的类型创建 Submap,因为该类型未在 XSD 文件中定义。如果类型在 WSDL 文件定义的话,也会发生这种情况。Submap 创建向导将不允许您使用非 XSD 定义的类型作为输入或输出来创建 Submap。对于这种情况,可以通过下面的操作将类型重构到 WSDL 文件以外:

  1. 在 Business Integration 视图中,在模块的 Data Types 类别或引用的库项目中找到所需的类型。
  2. 右键单击该类型并选择 Refactor > Extract In-lined Business Objects

提取了所需的类型后,可以使用所提取的类型作为输入或输出来创建 Submap。Submap 细分在处理本地元素或匿名类型时不可用。对于本地元素或匿名类型,可重用映射并不是一个好的选择。

New icon提示:如果一个模块或库中存在许多映射或自映射,那么可以使用 Data Map Catalog 来查看可用映射的详细摘要。要查看 Data Map Catalog,在 Business Integration 视图中选择一个项目,右键单击该项目并选择 Open Data Map Catalog

内置函数

您可以在 Mapping Editor 中使用一些常见的内置函数,比如 Concat、Normalize 和 Substring。除了这些函数外,还可以使用超过 60 多种 XPath 和 EXSLT Java™ 函数来轻松转换数据。下面的小节将介绍其中一些内置函数。XPath 和 EXSLT Java 函数 一节解释了如何使用其他函数。

Concat

Concat 函数将来自源的两个或多个字符串在目标端连接成一个单一的字符串值。内置的 Concat 函数支持在其属性页面内使用前缀、后缀和分隔符。

要在 表 1 所示的例子中实现理想的结果,可以通过下面的属性使用一个 Concat 转换:

  • 指定输入顺序,使 cityName 成为第一个输入,而 countryName 为第二个输入。
  • 在 cityName 输入中使用分隔符 “,”。
表 1. 示例用例数据
输入所需输出
<cityName>Toronto</cityName>
<countryName>Canada</countryName>
<destination>Toronto,Canada</destination>

Normalize

Normalize 函数将一个字符串从源移动到目标并在移动期间对字符串做出以下修改。

  • 删除前导和尾随空白。
  • 在字符串内使用单空格替换连续的空白。

要在 表 2 所示的例子中实现理想的结果,可以使用一个 Normalize 转换。

表 2. Normalize 示例
转换之前转换之后
<destination> Toronto Canada</destination><destination>Toronto Canada</destination>

Substring

Substring 函数将从一个源字符串中提取文本。Substring 函数使用一个分隔符和索引来判断要从进入的源字符串提取哪些文本。根据指定的分隔符,源字符串被划分为几个部分。索引用于识别您希望使用的字符串部分。默认情况下索引为 0,表示将使用第一个部分。例如,假设您希望从 <destination>Toronto, Canada</destination> 提取城市名。

可以使用 Substring 函数,将 “,”(逗号)指定为分隔符。默认情况下,索引 0 返回已划分的字符串的第一个部分,在本例中为 Toronto。

要从同一个字符串中提取国家名,指定 “, ”(逗号后加一个空格)为分隔符,并将索引设置为 1,这将使字符串的第二个部分被使用,本例中为 Canada。

如果不能确保在源字符串中使用逗号加空格,那么可以对 Custom 细分使用一个 XPath 表达式,比如:normalize-space(substring-after($destination, ","))

XPath 和 EXSLT Java 函数

New icon 可以使用 XPath 和 EXSLT Java 函数轻松地操作、评估和格式化数据。有许多这类的函数在 Mapping Editor 中受到支持,这些函数可以分为 String、Math、Boolean 和 Data and Time 几类。

String 函数

这些函数处理或返回字符串。Mapping Editor 中受支持的 string 函数的完整列表为:contains、format-number、local-name、name、namespace-uri、starts-with、string、string-length、substring、substring-after、substring-before、system-property、translate、align、array concat 和 padding。

作为演示其中一个这类函数的例子,让我们考虑 array concat 函数。array concat 函数获取一个字符串数组作为输入并在字符串输出中返回联接后的这些字符串。

作为一个例子,考虑 表 3 中的 array concat 函数。

表 3. Array concat 示例
输入输出
<input>A</input>
<input>B</input>
<input>C</input>
<input>D</input>
<output>ABCD</output>

在 Mapping Editor 中创建了一个 array concat 函数后,Properties View 中的 General 选项卡包含一个表,用于指定函数的输入参数。这些参数的值为 XPath 表达式,并且可以利用表示输入连接的转换变量。默认情况下,输入连接变量被用作到一个函数的输入;然而,可以根据需要进行编辑。

General 选项卡和输入参数表对于所有其他 XPath 和 EXSLT 函数都很常见。一些函数包含可选的输入参数,可以根据需要添加或删除它们。

Math 函数

这些函数将处理或返回数值。Mapping Editor 中受支持的 math 函数的完整列表为:ceiling、count、floor、number、round、sum、abs、acos、asin、atan、atan2、constant、cos、exp、log、max、min、power、random、sin、sqrt 和 tan。

Boolean 函数

这些函数将处理或返回 Boolean 值。Mapping Editor 中受支持的 Boolean 函数的完整列表为:boolean、false、lang、not 和 true。

Date and time 函数

这些函数将处理或返回日期和时间值。Mapping Editor 中受支持的 date and time 函数的完整列表为:date、dateTime、dayAbbreviation、dayInMonth、dayInWeek、dayInYear、dayName、dayOfWeekInMonth、Formate date、hourInDay、leapYear、minuteInHour、monthAbbreviation、monthInYear、monthName、secondInMinute、time、weekInYear 和 year。

不需要向转换提供任何输入,您可以用 dateTime 函数获得当前日期和时间。还可以使用其他日期和时间函数来获得当前值,而且也不需要提供输入。例如,对 Wednesday 使用 dayAbbreviation 函数(不提供输入)将产生一个目标值 Wed

Format date 函数非常有用,可以根据指定的模式转换给定的 dateTime,如 表 4 所示。

表 4. Format date 函数示例
转换之前模式转换之后
Wednesday January 27, 2010yyyy-MM-dd hh:mm:ss2010-01-27 06:29:25
Wednesday January 27, 2010MMMM dd, yyyyJanuary 27, 2010

Properties View 中的 General 选项卡需要配置 Format date 函数。Date and time 输入参数是一个 XPath 表达式,该表达式默认情况下使用变量表示函数的输入连接。此外,还可以进行编辑来输入用户定义的 XPath 函数。

在 Format date 函数属性的 General 选项卡内还可以使用一个日期选择器,它可以作为输入的日期和时间使用。选择一个日期将生成 XPath 字面表达式作为函数输入,表示所选的日期和时间 。

Format date 函数还包含一个模式,指定如何将给定的日期和时间格式化。可以从组合框中选择许多预定义的模式,或者可以输入一个用户定义的模式。并且,如果在源元素(由输入数据结构中定义)中指定了模式,那么用于表示输入连接的 XPath 变量也可以被作为模式使用。

最后,为 Format date 函数提供了一个示例字段来展示输出中应该提供的信息。

Lookup

New icon 可以使用一个 Lookup 细分来根据键查找值。这里的原理是 lookup 的源输入被作用一个键。lookup 将使用该键来为目标检索值。lookup 使用一个查找引擎来关联键和值。下面的查找引擎是由 Mapping Editor 提供的:

  • Comma Separated Value 文件查找:CSV(逗号分隔值)查找引擎将使用一个逗号分隔值文件来执行一次查找。CSV 文件的每一行都被看作为一个新条目。CSV 文件的第一行可以是该文件的列标题。当在 CSV 文件中执行一个查找时,属性允许您指定将哪个列用作键列,以及将哪个列用作值列。您可以使用以 0 开头的索引或列标题名指定列。要理解 CSV 文件中的列,考虑以下数据:
    State Name, Abbreviation, Old GPO, FIPS
    Alabama, AL, Ala., 01
    Alaska, AK, Alaska, 02
    Arizona, AZ, Ariz, 04
    Arkansas, AR, Ark., 05

    如果使用以上 CSV 文件根据国家缩写检索一个国家名,您可以设置查找来使用列 1 作为键列,并将列 0 作为值列。或者,还可以设置查找来使用 “Abbreviation” 列作为键列,并使用 “State Name” 列作为值列。无论哪一种情况,键 AK 都将返回值 Alaska。

    要使用 CSV 查找,CSV 文件必须使用 *.csv 作为文件扩展名。CSV 文件必须位于与映射文件相同的项目内,或者位于一个相关项目内。

  • 属性文件查找:属性文件查找使用 “key=value” 格式的文件执行查找。
  • 关系查找:关系将使用一个现有的静态关系执行查找。静态关系在 WebSphere Integration Developer 中指定,用于描述静态的关联。例如,必须定义一个关系来将国家名和国家缩写联系起来。一旦定义了一个关系后,映射内的查找可以使用该关系来检索值。属性允许您指定将关系中的哪个角色作为键,哪个角色作为值。

下面的例子演示了 Lookup 映射的使用。让我们查看 图 2 所示的 CSV 文件。

图 2. 示例 CSV 文件
示例 CSV 文件
示例 CSV 文件

在本例中,输入文件将包含一个国家名缩写,并且输出将需要如 图 3 所示的完整名称。

图 3. Lookup 映射
Lookup 映射
Lookup 映射

以上查找的属性如 图 4 所示。

图 4. Lookup 属性
Lookup 属性
Lookup 属性

以上映射的结果如 图 5 所示。

图 5. 映射结果
映射结果
映射结果

也可以创建一个定制的查找引擎。产品帮助中的 创建定制查找 主题解释了定义定制查找引擎的过程。

其他细分

本文未提及的其他细分主要用于处理数组和其他结构化数据。关于更多信息,参见第 2 部分的 使用数组Custom

条件映射

映射内的转换经常要依赖于多个条件。这些条件用于确定某个特定的映射是否会在运行时出现,从而提供一种方式来控制映射的逻辑流。Mapping Editor 支持使用 If、Else if 和 Else 转换对映射实现这类条件逻辑。这些转换根据给定的 XPath 表达式条件对映射进行分组。此外,通过直接提供 XPath 表达式或使用静态的 Java 方法调用,XML Mapping Editor 还支持对单独的映射使用条件。最后,还会对连接到源数据(可选的)的转换自动应用隐含的条件。只有运行时期间存在源数据时,才会执行任何对可选源数据进行操作的转换,否则,将不会发生转换。

If、Else if 和 Else 细分

New icon If、Else if 和 Else 细分是一些条件转换,用于控制映射内的映射流。这些细分中的每一个都属于容器转换,即它们需要包含嵌套映射来提供任何有用的实现。由于 If、Else if 和 Else 细分都是容器转换,这些容器提供了一种方法来根据已知的条件对所需的映射进行分组。

在 Properties 视图的 Condition 选项卡内,将 XPath 表达式应用到 If 和 Else if 细分,即对它们应用了条件。Else 细分可以仅依赖于相关的 If 或 Else if 细分,不需要应用任何的条件。参见 XPath 条件 一节来理解这类表达式的计算方式。

在 Mapping Editor 内创建 If 细分类似于创建其他转换。在源元素和目标元素之间创建一个连接并将转换类型更新为 If 细分。创建了 If 细分后,可以添加 Else if 或 Else 细分,方法就是从 hover 动作栏或上下文菜单中选择 If 细分并调用 “Add Else if” 或 “Add Else” 操作。创建了 Else if 或 Else 细分后,您必须添加一个目标连接来提供该细分将在输出中填充的内容的上下文。类似地,可以选择性添加一个源连接来提供细分的输入上下文。与其他细分不同,If、Else if 和 Else 细分都可以具有多个输入和输出连接,这为嵌套映射将操作的内容提供了基础。

If、Else if 和 Else 细分被组合在一起来解释彼此之间的关联。当一个映射包含 If、Else if 或 Else 细分的组合时,将在运行时根据提供的条件只执行该组中的某一个细分,或者都不执行。只有包含条件的第一个 If 或 Else if 细分(细分的值为 true)将得到执行。否则,如果组中的所有其他相关条件失败,那么将执行 Else 细分。一旦这些细分中的某一个得到执行,与该条件细分相关的所有嵌套映射都将在运行时得到执行。

在对包含 If、Else if 和 Else 细分的组合创建目标连接时需要十分小心,因为对这些细分应用了下面的限制:

  1. 包含 If、Else if 和 Else 细分的组合内的所有目标连接必须针对目标数据结构中的兄弟(sibling)元素。如果不满足这一限制的话,那么将导致下面的错误:“All of the transformations in the Else if transformation group do not target elements that are siblings of each other”。要修复这个问题,确保该细分的条件组合内的所有目标连接都彼此互为兄弟连接。
  2. 不相关的转换输出不能出现在条件转换组合的输出中。不相关的转换是指那些未包含在 If、Else if 和 Else 细分中的转换。条件转换组合的输出范围被定义为介于最顶级的连接输出元素和最底层的连接输出元素之间。如果不能满足这一条件,那么将导致以下错误消息:“The Move transformation exists outside the output scope of the conditional transformations, which is not valid”。要解决这个问题,将不相关的转换放入其中一个条件转换中(或在所有条件转换中复制该转换,如果适应于所有情况的话)。下面解释了一个条件分组范围的例子,如 图 6 所示。
    图 6. 条件映射
    条件映射
    条件映射

    注意,条件转换分组的输出范围介于元素 “field1” 和元素 “field5” 之间。其他不相关的转换不会介入到这个突出显示的区域中,除非转换被包含到其中一个 If、Else if 或 Else 细分中。

单一转换条件

有些时候,某个转换只需要一个单独的条件来执行所需的映射。在这种情况下,可以对单独的转换应用一个 XPath 表达式,而不涉及 If 细分。与对 If 细分添加 XPath 表达式十分类似,可以使用 Properties 视图中的 Condition 选项卡对转换添加一个条件。

为了更好地理解单一转换条件和 Mapping Editor 中内置的隐含条件,考虑这样一个场景,您希望使用源中给出的某个输入字段的值。否则,您将使用不同输入字段的值。考虑下面的场景:

输入:

  • 对于特定的推荐(recommendation)使用可选的字符串输入。
  • 对于一般的推荐使用必需的字符串输入。

输出:

  • 使用尽量具体的单个推荐。当给出具体的推荐时,将使用该推荐。否则,将使用一般的推荐。

在本例中,可能需要考虑以下操作:

  • 在特定的输入推荐和输出推荐之间创建 Move 细分。当给出特定的推荐时,将执行 Move 并相应地设置值。由于将为可选的输入自动生成条件,因此无需向这个转换添加任何额外的条件。
  • 在一般输入推荐和输出推荐之间创建 Move 细分。对 Move 使用下面的条件,这样将只有在输入中没有给出特定推荐时执行它:not(/body/response/specificRecommendation)

使用条件的另一种方法就是向可重复元素列表应用一个过滤。有关更多信息,请参见第 2 部分中的 筛选数组

XPath 条件

可以使用 XPath 表达式为 If、Else If 或其他细分编写条件。在计算 XPath 表达式时,条件的值将根据表达式的返回值确定,如 表 5 所示。

表 5. XPath Condition 计算标准
表达式返回类型结果为 True结果为 False
节点集非空节点集空节点集
字符串包含一个或多个字符的字符串零长度的字符串
数字任何非零数字(负数或正数)
布尔truefalse

在使用 XPath 编写条件时,可以使用相对或绝对路径。转换的输入可以作为变量提供并被插入到表达式中。可以在条件输入区域中使用内容帮助(content assist)来查看可用变量列表。还可以在条件输入区域中使用内容帮助来利用 XPath 函数。要在条件输入区域中调用内容帮助,使用 CTRL+Space

在使用相对路径时,您目前无法 使用 ../<element name> 之类的语法引用以上上下文节点。如果需要访问其中一个输入值中无法访问的信息,那么使用绝对路径。对于使用变量的例子,图 7 中的内容帮助显示了 cityName 可以作为变量使用:

图 7. XPath 内容帮助
XPath 内容帮助
XPath 内容帮助

单击上表中的 cityName 变量后,“$cityName” 将被插入到 entry 字段,您可以继续创建条件,比如 $cityName = "Toronto"

要了解使用条件的基本知识,考虑下面这个例子。一个旅游公司为客户提供有关旅游目的地的咨询,使用以下提示的其中一种形式:

  • 天气将会很 —— 需携带防晒油。
  • 天气将会很 —— 需携带皮大衣。

提示取决于所选择的旅游目的地的温度。对于温度在 0°C 之上的旅游目的地,将给出天气炎热的提示。相反,如果温度低于 0°C,将提示天气寒冷。可以按照如下所示对映射使用条件:

  1. 从源 celsiusTemperature 元素中创建 If 细分,这将针对输出中的 advisory 元素。
  2. 在 If 细分中,作为条件添加 XPath 表达式 $celsiusTemperature > 0
  3. 向 If 细分添加 and Else 细分并针对输出中的 advisory 元素。
  4. If 细分内添加嵌套的 Assign 转换,其值为 “Weather will be hot -- bring your sunscreen”。
  5. Else 细分内添加嵌套的 Assign 转换,其值为 “Weather will be cold -- bring your parka”。

Java 条件

还可以使用对静态 Java 方法的调用来构建条件。在使用 Java 方法调用时,方法的返回值将确定条件的结果,如 表 6 所示。

表 6. Java 条件计算标准
方法返回类型True 条件False 条件
org.w3c.dom.NodeList非空节点列表空节点列表或 null
字符串包含一个或多个字符的字符串零长度的字符串
int任何非零数字(负数或正数)
布尔truefalse

要编写 Java 方法来计算条件逻辑:

  1. 在现有 Java 项目中创建新的静态 Java 方法,或创建新的 Java 项目来存储方法。
  2. 确保您的映射项目或其中一个库依赖关系包含对 Java 项目的依赖。
  3. 单击 Java Imports 属性页面并单击 Add 按钮。接下来,指定前缀和相关的 Java Class。
  4. 在 condition entry 字段中,使用内容帮助(通过按下 CTRL+Space 获得)插入合适的方法调用。

例如,假设您拥有下面的内容:

类:TravelCompanyUtilities
方法:isDesirableCity
参数:cityName (of type String)

条件看上去类似如下所示:

TravelCompanyUtilities::isDesirableCity(/body/response/destination/cityName)

或者

TravelCompanyUtilities::isDesirableCity($cityName)

提示和技巧

本节将包含一些提示和技巧,帮助简化 XML 映射的创建。本节涉及的提示包括:

  • 用于加快处理的技巧:匹配映射,内容帮助。
  • 用于处理大型模式的技巧:滚动、过滤、导航轨迹(Navigation trail)。
  • 其他技巧:Test map 视图,对转换排序、查看模型组、移动映射。

匹配映射

当源和目标类似或包含类似内容时,可以使用匹配映射。匹配映射始终尝试匹配编辑器的源内容与目标端内容。不需要进行选择。当源端的元素或属性拥有和目标端的元素或属性相同的名称时,将生成一个匹配。匹配的元素的类型必须类似,这样匹配才能生成有用的映射。如果匹配的类型比较复杂,那么将使用一个容器映射来在最高级别进行匹配,然后将在容器映射内部继续匹配映射,直到找到全部匹配。要调用匹配映射,使用 “Map source to target based on the name and types” 工具栏按钮(Map source button)。匹配映射将始终使用容器映射(例如,Local 映射,或对数组使用 For each)来映射复杂类型,而不是使用 Move,这将可以更简便地调整所创建的映射。

例如,如果使用 Move 转换将源内容体映射到目标内容体,并且您希望对内容体进行一些轻微的调整,那么您需要删除 Move 转换并在一个更细粒度的层次上创建各个转换。然而,在使用匹配映射时,将使用容器映射,并且钻取这些容器映射将允许您获得发生修改的准确位置。通过这种方式,只有与微小调整对应的转换需要进行修改。

当源和目标具有同类型的类似字段时,但是可能具有不同的名称,可以使用 Local 映射来匹配这些类似的类型,然后在您创建的 Local 映射内使用匹配映射。例如,假设我们具有如下源和目标,如 图 8 所示。

图 8. 调用匹配映射之前的映射编辑器
调用匹配映射之前的映射编辑器
调用匹配映射之前的映射编辑器

在这个级别调用匹配映射将不会找到任何匹配,并将显示一条错误消息,表示没有为目标中的 “getWeather” 元素找到任何匹配。然而,目标中的 GetWeather 元素正在查找 cityName 和 countryName,这些内容将来自源端的 destinations 数组的第一个元素。我们可以为匹配映射重置起点,方法是在源的 destinations 元素和目标的 GetWeather 元素之间创建一个 Local 映射,如图 9 所示。

图 9. 调用匹配映射之后的映射编辑器
调用匹配映射之后的映射编辑器
调用匹配映射之后的映射编辑器

从 Local 映射内,调用匹配映射将映射 CityName 和 CountryName。

内容帮助和 XPath Expression Builder

Mapping editor 的属性页面中使用的一些条目字段包含内容帮助,可以在使用重要语法时提供帮助。如果内容帮助可用于某个条目字段,那么该条目字段旁将显示一个电灯泡图标(Light bulb icon),并且电灯泡图标的悬浮帮助将指出内容帮助是否可用。要调用内容帮助,使用 CTRL+Space

在编辑 XPath 表达式时,内容帮助将包含一个名为 “Insert Simple XPath” 表达式的菜单项。单击此菜单选项将显示 “Simple XPath Expression Builder” 对话框。XPath Expression Builder 帮助创建简单的 XPath 表达式,如 图 10 所示。

图 10. 简单的 XPath 表达式构建器
 简单的 XPath 表达式构建器
简单的 XPath 表达式构建器

滚动

当在编辑器内创建一个转换或映射时,通常按照下面的方式创建:找到一个源输入字段、单击源输入字段、按下鼠标按钮、将连接拖拽到目标字段,最后松开鼠标按钮以完成操作。使用这种方法非常快速、简便,但是同时禁用了编辑器的滚动条。这样的话,如果要执行的转换的源和目标字段不能同时显示在视图中,那么将很难处理这种大型模式。对于无法同时显示的源和目标,可以使用下面的方法来创建转换。

  1. 将鼠标放到源输入字段上方,单击显示的拖动句柄,但是不要按下鼠标按钮,如 图 11 所示。
    图 11. 拖动句柄
    拖动句柄
    拖动句柄

    这将发起一个创建连接的过程,同时仍然保留了使用滚动条的能力。如果连接线(connection wire)处于激活状态,那么就可以使用滚动功能,方法就是将鼠标悬浮到靠近编辑器边缘的位置并短暂停留。
  2. 选择源输入字段,同时不要按下鼠标按钮。滚动到目标中的适当匹配字段,按下 CTRL 键并单击目标字段来选择它。最后,右键单击目标字段并选择 Create Transform。将在所选的源和目标之间创建一个转换,并且稍后可以根据需要对转换进行定制。
  3. 选择源输入字段,右键单击并选择 Create Connection。出现连接线后,可以使用滚动条来查找目标字段并完成转换。在创建连接时,还可以使用滚动功能,即将鼠标放到靠近编辑器边缘的位置并短暂停留。

过滤

New icon 对于映射的输入或输出包含许多字段的情况,查找并导航到某个特定字段将非常繁琐。源和目标列中都提供了一个过滤器,可以使字段的查找变得非常容易。将一个过滤应用到某个源或目标列后,列将只显示字段名中包含过滤文本的字段。要使用过滤,在以下位置输入过滤文本并按下 Enter

图 12. 映射编辑器的源和目标过滤
映射编辑器的源和目标过滤
映射编辑器的源和目标过滤

要清除某个过滤,单击列底部的 <Show all> 或清除过滤文本。

导航轨迹

在创建 Local 映射等嵌套映射时,您会发现自己深陷一个元素结构中,您希望知道自己的精确位置。在编辑器的顶部是一个导航轨迹,它让您能够知道自己目前所在的元素位置,如 图 13 所示。单击导航轨迹的任何部分将快速在编辑器视图中呈现相关的嵌套级别。

映射编辑器导航轨迹
映射编辑器导航轨迹

Test Map 视图

在 Mapping Editor 中进行操作时,可以使用 Test Map 视图来在创建映射转换时测试它们。有关 Test Map 视图的细节,请参考 问题诊断 小节。

对转换进行排序

默认情况下,Mapping Editor 将根据源输入对转换列进行排序。这意味着转换本身将与相关的源输入字段进行匹配。某些情况下,按照目标输出对转换列进行排序会更方便。由于这将使转换最接近其目标输出,因此可以快速地查看特定目标上操作的转换的类型。要切换排序方法,右键单击映射编辑器区域并使用 “Sort Transforms” 菜单项,或单击本地菜单栏中所需的排序方法按钮(源中的 Sort method 或目标中的 Target method)。

查看模型分组

默认情况下,Mapping Editor 将使用 XML 输入和输出的简化视图。某些信息可能位于 Mapping Editor 在默认情况下未显示的模式中。例如,模式中定义的一个选项在模式编辑器中显示为一个扁平列表。要在 XML Mapping Editor 中查看这类模型分组信息,可编辑 XML Mapping 首选项来展示分组。要编辑首选项,单击 Mapping Editor 本地工具栏上的 Preferences(Preferences                     button)按钮。

除了 Mapping Editor 窗口中显示的细节外,还可以在 properties 视图中查看所选元素的一般信息。

移除

New icon 从版本 7.0 开始,Mapping Editor 支持剪切、复制和粘帖映射。剪切、复制和粘帖操作可用于下面的情况:

  • 映射可能会变得混乱,因为没有使用足够的容器映射。对于这种情况,可以创建新的容器映射并剪切(CTRL+X)新容器映射以外的现有映射,并将它们粘贴(CTRL+V)到新的容器映射。已粘帖的映射将被移入到新容器映射内部。有关映射组织的更多信息,参见 组织映射
  • 现有映射需要从一个目标移动到另一个。有些情况下,您可能已经创建了一个到某个目标的映射,并认识到您应该将此映射创建为从相同源到同一类型的不同目标。对于这种情况,可以剪切(CTRL+X)现有映射,选择正确的目标字段然后选择粘帖(CTRL+V)。
  • 现有映射需要针对不同的源和目标复制。如果已经在源和目标之间创建了映射,那么您会认为您需要在不同的源和目标之间创建相同的映射,这两个源和目标具有与初始的源、目标相同的类型,可以复制(CTRL+C)现有映射,选择新的理想的源和目标因素(按住 CTRL 键进行多个选择),然后调用粘帖(CTRL+V)。
  • 来自一个文件的映射需要在另一个文件中复制。只要源和目标类型相同,您就可以使用复制和粘帖将映射从一个文件复制到另一个。首先在一个文件中(CTRL+C)复制映射,转到新文件,选择新的源和目标字段(使用 CTRL 键选择多个项),然后调用粘帖操作(CTRL+V)。

问题诊断

在创建映射时,最好定期对其进行测试,以确保获得理想的结果。

输入文件

要在工具中测试映射,第一步是创建或选择一个要进行测试的输入文档。最简单的方法就是使用 Mapping Editor 附带的输入文档生成工具。这些工具将根据输入 XML 模式创建一个基础的输入文档。一旦生成输入文档后,可以立即开始测试,稍后可以增加更多的元素和值来充实输入。使用下面的方法来创建输入文档:

  1. 在中介流中,在使用来自 XSL Transformation 原语的 Create New XML Mapping 向导时,需要选中 Create a sample XML input 文件来测试 XML Map 复选框。
  2. 在 Mapping Editor 内,可以单击 Associate XML files 工具栏图标,随后使用 Generate Input 按钮来创建并关联一个新的样例输入文件。

    如果映射的根输入不是全局元素,那么将禁用 Generate Sample Input File 按钮。具有全局元素的映射只能通过从另外的映射中调用它们来进行测试。

  3. 在 Mapping Editor 内,可以单击 Test Map 工具栏按钮来打开 Test Map 视图。从 Test Map 视图中,单击 Associate XML files 工具栏按钮并随后使用 Generate Input 按钮来创建并关联新的样例输入文档。

作为一种创建样例输入文件的替代方法,如果已经有了一个样例输入文件,那么可以使用 Associate XML 文件工具栏操作将现有 XML 输入文件与映射文件关联起来。目前,输入文件通常被保存到与它们所应用到的映射相同的项目内,并显示在 Transformations > Data Map Test Data category 下的 Business Integration 视图内。

使用 Test Map 视图反复测试

一旦将样例输入文件与映射文件关联在一起后,可以使用 Test Map 视图来测试映射文件。当您正在开发映射时可以使用这种测试方法。该视图将使用您在自己的映射文件中实现的任何转换对输入文档执行转换,即使您还没有将更改保存到映射文件。这可以确保在将更改提交到映射文件之前您创建的转换具有理想的结果。要打开 Test Map 视图,使用映射编辑器工具栏上的 Test Map 动作(Test map action)。

在使用 Test Map 视图时,通过单击 Test Map 视图工具栏上的 Run transformations 按钮,可以随时刷新输出。还可以从 Test Map 视图中对输入 XML 文件进行更新,通过单击 Save selected input file 工具栏按钮还可以保存这些更改。使用 Save selected input file as 工具栏按钮,对 XML 文件的修改还可以提交到一个新的输入文件。

Test Map 视图提供了两种方法来查看输入和输出 XML。visual 选项卡以一种树形格式表示 XML,允许您轻松地导航和编辑值。visual 选项卡还提供了一些验证,比如检验分配给一个简单类型的值是否有效。

使用 Integration Test Client 测试映射

除了 Test Map 视图外,还可以使用 Integration Test Client 测试一个完整的 XML Map。可以保存在测试客户机中创建的测试并在以后重新运行它们。在使用 Integration Test Client 进行测试时,还可以调试映射转换。

要使用 Integration Test Client 测试一个映射文件,在 Business Integration 视图中右键单击某个 XML 映射文件并选择 Test。还可以在中介流中选择一个 XSL Transformation 节点并右键单击它来调用 Test XML Map 操作。

要在使用 Integration Test Client 时调试映射,在运行事件之前,选择 Invoke XML Map Event 详细属性中的 Stop for debug before transformations 复选框。还可以在 Mapping Editor 中对转换设置断点,方法是右键单击转换并从 “Debug” 菜单中选择一个操作。

在服务器中测试映射

在使用以上测试方法时,映射是使用工具进行本地测试的。有些情况下,映射可能会在工具中成功执行,但是当运行在服务器中时,会在运行时出现错误。对于这种情况,将需要在服务器上调试问题。

服务器上的 XML 映射测试就是指对包含待测试的 XML Map 的组件进行测试。在 Assembly Editor 中,右键单击包含要测试的映射的中介流或业务流程流组件,并使用 Test Component 或 Test Component in Isolation 调用 Integration Test Client。

要理解中介流中的 XSL Transformation 原语如何在运行时执行,考虑如 图 14 所示的场景。

图 14. XSLT 原语
XSLT 原语
  1. SMO 输入对象被 “SortDestinations” XSL Transformation 原语接收。
  2. SMO 输入被序列化为 XML 以进行处理。
  3. XML 输入使用与原语相关的 XSL 文件进行转换,并将生成一个 XML 输出。
  4. 输出 XML 被反序列化到 SMO 输出对象中。

Integration Test Client 中的细粒度的跟踪将允许您查看中介流中每个 XSL Transformation 原语的输入和输出。大多数情况下,如果 XML 在本地测试时正常,但在运行时故障,那么问题将出现在上面所示的步骤 4,即从输出 XML 到 SMO 对象的转换。在这一点上,输出 XML 和模式之间的不一致将导致出现故障。为了有助于诊断并修复这类问题,可以启用服务器跟踪来使您能够对消息进行检查。

注意:目前,细粒度跟踪只能用于 Mediation Flow 组件,Business Process Flow 目前还不支持。

要启用服务器跟踪:

  1. 在 Servers 视图中,在服务器运行时,右键单击适当的服务器并选择 Administration > Run administrative console
  2. 登录到管理控制台(admin 是默认的 ID 和密码)。
  3. 在 Troubleshooting 部分中,选择 Logs and Trace
  4. 在 Logging and Tracing 区域中,选择服务器名,比如 server1。
  5. 单击 Change Log Detail Levels
  6. 在 Change Log Details Level 条目字段中,添加如下文本到该条目字段中已有的任意文本:: com.ibm.ws.sibx.*=all

    例如,如果条目字段在进行一个更改之前包含这个内容:*=info

    该条目字段在修改后将类似于 *=info: com.ibm.ws.sibx.*=all

  7. 单击 OK
  8. 单击 Save 保存修改并将配置修改推到服务器。
  9. 登出管理控制台。
  10. 重启服务器。

启用服务器跟踪后,重新运行测试并查看 trace.log 文件。要判断 trace.log 文件的位置:

  1. 打开 Server Logs 视图。
  2. 在 Server Logs view 工具栏中,单击 Load server console or log 按钮。
  3. 选择 Load from server log directory
  4. 单击 Browse
  5. trace.log 文件选中复选框并单击 OK
  6. 注意 trace.log 文件的位置并单击 Cancel

    注意:尽管可以使用查看器来查看 trace.log 文件,但是使用文本文件编辑器查看日志文件时,查找所需的跟踪信息变得更加容易。

打开 trace.log 文件时,可以定位序列化的 SMO 实例,只需要搜索字符串 <smo

通过查找下面的字符串,还可以查看位于转换原语之前和之后的原始 XML 数据:

Serialized DataObject prior to transformationResult of transformation

另一个调试选项是在 Mediation Flow Editor 中对 XSL 转换原语设置断点。调试器将允许在运行时检查位于 XSL 转换原语前后的 SMO 值。

最佳实践

组织映射

在使用 Mapping Editor 时,可以使用一些最佳实践来使映射更易于导航、理解和维护。实现映射的一个技巧就是首先逐一观察目标中的字段。对于目标中的每个字段,考虑下面的问题:

  • 目标字段是否需要填充(有无必要)?
  • 如果目标字段需要填充,将使用来自哪些位置的数据?
  • 如果将使用来自源 XML 的数据填充目标,数据位于源中的哪些位置?
  • 数据源的类型是否与目标数据类型相同?如果类型相同,并且不需要以任何方式修改数据,那么考虑使用 Move 转换。
  • 如果来自源和目标的数据不是同一类型或者需要对数据进行处理,考虑使用 Local map 或一个 Submap 来映射源和目标。通过使用 Local map 或 Submap,可以在子转换中嵌套映射的细节,在映射文件的根级别减少混乱和混淆。
  • 未来是否需要在另一个映射中映射源和目标(或在当前映射中多次映射)?如果您认为这些类型的映射会出现得很频繁,那么考虑使用可重用的 Submap。否则,使用 Local map。
  • 如果需要多个源输入来填充某个目标,那么考虑使用一个 Merge,这是一个特定的 Local map,接受多个输入。
  • 在 Submap 或 Local map 中,是否有大量源和目标字段具有相同的名称和类型?如果源和目标非常相似,那么考虑使用 Match Mapping 来映射相似的字段,以此作为未来定制的基础。
  • 对于作为映射目标的复杂类型,确保除了在父级别在容器映射中定义的那些映射外,目标类型的子类型不会是任何其他映射的目标。例如,假设您希望将所有上下文信息从源中复制到目标,但是还希望将消息体中的某些内容添加到上下文或关联。正确的方法如 图 15 所示。
    图 15. 处理嵌套映射的正确方法
    处理嵌套映射的正确方法
    处理嵌套映射的正确方法

    图 16 是错误的,因为上下文中有一个 Move,而 contextor 关联中有另外一个 Move。

    图 16. 处理嵌套映射的错误方法
    处理嵌套映射的错误方法
    处理嵌套映射的错误方法

    图 17 也是不正确的,因为上下文或关联的 Move 不在上下文定义的 Local map 中。

    图 17. 处理嵌套映射的错误方法
    处理嵌套映射的错误方法
    处理嵌套映射的错误方法

    即使上下文中的 Local map 没有映射关联元素,该 Move 仍然是错误的,因为它必须位于 Local map 中。

在根基本对每个目标字段确定了最佳映射类型后,可以使用相同的过程来在已创建的 Local map、Merge 和 Submap 转换内创建映射。

在组织映射时,下面的操作也许会很有用:

  • Cut, copy, and paste:参考 移动映射,获得更多信息。
  • Refactor to submap:如果已经创建了一个 Local map,并且后来觉得它更适合作为可重用的 submap,那么右键单击现有的 local map 并调用 Refactor to submap 操作。

将映射迁移到 Integration Developer

大多数情况下,Integration Developer 早期版本中创建的 .map 文件可以很好地在新版本中工作。然而,有时会出现一个警告消息,表示与给定映射关联的 XSL 文件是使用早期版本生成的。对于这种情况,我们建议重新生成 XSL 文件。XSL 可以使用 Problems 视图中的警告消息附带的快速修复重新生成。或者,在 Mapping Editor 中打开 .map 文件时,通过使用 Mapping Editor 本地工具栏中的 “Generate XSLT script” 按钮生成。

一般迁移规则的一个例外就是 XML 映射的格式在 Integration Developer V6.0.2 和 Integration Developer V6.1 之间出现了显著的变化。Integration Developer 提供了一种工具,可以将 Integration Developer V6.0.2 XML 映射文件 (.xmx) 迁移到更新的 Integration Developer V6.1.2 和更新格式 (.map)。导入包含 *.xmx 文件的项目后,将在 Problems 视图中收到警告消息。要启用该迁移工具,右键单击警告消息并选择 Quick Fix,或尝试在 Integration Developer V6.1.2 或更高版本中打开 *.xmx 文件。

完成了自动迁移后,仍然需要对迁移后的映射文件进行测试,以确保它生成了理想的结果。在 V6.0.2 中,在目标 XML 中为必要的元素生成了空元素,即使这些元素没有在映射中进行映射。然而,在 V6.1.2 或更高版本,这些空元素不再被创建,除非您显式创建了映射。由于这两个版本之间的种种差异,我们建议您在完成迁移后对映射进行测试。

本系列的第 2 部分 处理复杂的 XML 结构 解释了更加高级的 XML 映射主题。

结束语

在本文中,您了解了如何使用 WebSphere Integration Developer V7 创建、构建和测试 XML 映射,以及如何使用 XML Mapping 编辑器中的各种可用细分创建简单映射。您现在已经掌握了足够的技能来在 WebSphere Integration Developer 中设计、开发和部署 XML 映射。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=493297
ArticleTitle=WebSphere Integration Developer V7 中的 XML 映射,第 1 部分: 使用 Mapping Editor 开发映射
publish-date=05312010