当前位置:   article > 正文

处理复杂的XML结构

@webparam定义复杂xml

这个由2部分组成的系列文章的第1部分, 使用XML映射编辑器开发地图 ,向您展示了如何使用IBM®WebSphere WebSphere Integration Developer V7.0.0(以下称为Integration Developer)快速创建健壮且组织良好的XML映射。 它还描述了可用于测试和调试地图的工具,以使问题确定更加容易。 本部分(第2部分)向您展示如何执行更复杂的XML映射。

处理数组

源或目标中的某些字段可能是可重复的,在这种情况下,存在一系列特定元素。 通常,在使用数组时,总是从将输入数组映射到输出数组开始,这将创建一个For-each转换, 如图1所示。

图1.使用数组
处理数组

我们不建议您直接映射数组元素的子级,而不在父数组上使用For-each。 例如, 图2不是完成与上述图2相似的映射的推荐方式。

图2.使用数组
处理数组

默认情况下,将输入数组连接到For-each转换时,它将导致对输入数组中的所有元素进行迭代,从而将根据For-each映射中定义的嵌套映射来映射每个数组元素。

类似于本地映射,For-each是不会产生任何结果的容器映射,除非有嵌套的映射定义了如何对输入数组的每次迭代进行操作。 因此,您必须指定有关将源中的哪些字段映射到目标中的哪些字段的特定详细信息,以完成For-each实现。 例如, 图3显示了For-each映射内的嵌套映射。

图3.每个嵌套嵌套映射
每个嵌套映射

使用数组时,这可能会遇到其他一些情况。

方案1.从源数组到单例目标字段的映射

与处理数组的一般情况一样,您仍然要从在源数组元素和目标字段之间创建映射开始。 在这种情况下,该顶级映射将是Local map或Move,因为For-each仅在源和目标是数组时才适用。 在这种特定情况下,您需要确定要使用哪个输入数组元素。 您可以在“属性”页面的“基数”选项卡上为本地地图或“移动”变换设置适用的数组索引。 在“基数”选项卡上指定索引时,索引从1开始而不是0。

为了说明这种情况,请考虑图4中的以下示例以及以下源和目标。

图4.映射前的单个目标
映射前的单个目标

在这种情况下,源包含一组具有城市和国家名称的目标对象,但是目标仅期望一个城市名称和一个国家名称。 在这种情况下,您要获取目标数组的第一个条目,并将其城市和国家/地区名称映射到目标单例。 第一步是在数组和包含要填充字段的目标项目之间创建一个Local映射,如图5所示。

图5.映射后的单个目标
映射后的单个目标

创建该本地映射后,设置基数以指示第一个数组条目将是本地映射转换的输入。 在Local map中,destination元素的字段与GetWeather元素的适当字段匹配,如图6所示。

图6.本地嵌套映射
本地嵌套mappin

方案2。从单例源字段映射到目标中的数组

在这种情况下,假设目标数组仅包含一个元素,则再次需要在源字段和目标数组之间创建一个Local map。 在“本地”地图中,填写有关源地图中哪些字段到目标中哪些字段的详细信息。

您可以通过创建指向数组的多个本地映射并在“属性”页面的“基数”选项卡上指定不同的索引来填充目标数组中的多个元素。 您还可以使用“合并”转换来使用源中两个或多个不同单例中的信息来填充目标中的数组元素。 在“基数”选项卡上指定输出数组索引时,索引从1开始而不是0。

方案3.从源中的多个阵列映射到目标中的单个阵列

在某些情况下,您可能要在源中使用两个或多个数组来在目标中创建单个数组。 在这种情况下,您可能需要两个结果。 一个结果可能是合并输入数组中的条目以形成目标数组的单个条目。 另一个期望的结果可能是将输入数组中的条目附加在一起以形成更长的输出数组。 合并和附加情况都在下面说明。

情况1-合并

在这种情况下,您要将源中的两个阵列合并到目标上的单个阵列中。 例如,考虑源包含两个单独的数组的情况:名称数组和电话号码数组。 假设电话号码列表与名称列表一一对应,并且您的输出数组包含需要名称和电话号码的元素,则可以将两个单独的数组中的信息合并到目标上的单个数组中侧。

在这种情况下,可以使用“合并”变换来完成所需的结果。 与For-each相似,Merge转换是一个容器映射,它不会产生任何结果,除非有嵌套的映射定义了如何对输入数组的每次迭代进行操作。 因此,您必须指定有关将源中的哪些字段合并到目标中的哪些字段的详细信息,以完成“合并”实现。 注意在合并中如何执行迭代:该过程开始于获取所有输入数组的第一个索引并将这些字段合并到目标数组的第一个索引中。 然后,获取所有输入数组的第二个索引以生成目标数组的第二个索引,依此类推。 一种简单的合并方法是,如果您将两个相同大小的数组合并在一起,则会得到与原始数组大小相同的目标数组。 图7显示了一个示例。

图7.合并映射
合并映射

如果合并转换的输入数组的大小不同,则可以在“基数”属性页面上指定要迭代的输入。 默认情况下,迭代将设置为合并变换的第一个输入。 但是,指定当输入数组的大小不同时要迭代的输入数组将在目标数组上产生不同的结果。 以图8图9中的以下两个示例为例,说明已知输入数组大小不同时的区别。

图8.合并不同大小的数组
合并不同的数组大小
图9.合并不同大小的数组
合并不同的数组大小

在以上示例中,生成的目标数组大小直接取决于选择要迭代的输入数组。 在映射执行期间已知输入数组大小相同的情况下,选择要迭代的输入无关紧要,因为会产生相同的结果。

情况2-追加

在这种情况下,您要从一个源数组中获取所有元素,并从另一源数组中获取所有元素,并在目标端创建一个包含两个源数组中所有元素的数组。 例如,假设您在源上有两个旅行目的地列表,并且想在目标上创建一个包含所有目的地的列表。

在这种情况下,您可以使用Append变换完成所需的结果。 考虑追加的一种简单方法是,如果采用两个任意大小的数组,并将它们附加在一起,则会得到目标数组,该数组是输入数组大小的总和。 图10显示了一个示例。

图10.追加映射
追加映射

与For-each相似,Append转换是一个容器映射,除非有嵌套的映射定义如何对输入数组的每次迭代进行操作,否则它不会产生任何结果。 因此,您必须指定有关如何将源中的字段添加到目标中的字段以完成Append实现的详细信息。 实施追加转换时,将使用For-each和Move映射自动为您生成嵌套映射的第一层。 在嵌套的For-each映射中,需要进一步的映射才能完成实现。

通过获取第一个输入数组的第一个索引以在目标数组中产生第一个索引,在追加中执行迭代。 然后,采用第一输入数组的第二索引来生成目标数组的第二索引。 此过程将继续进行,直到对第一个输入的所有元素都进行了操作,然后再处理(逐个)第二个输入数组的所有元素,依此类推。 输入数组的附加顺序基于它们进入Append变换的顺序。 如果需要,可以在“追加”变换的“订单属性”页面中对此进行修改。

排序数组

使用源数组作为转换的输入时,可以选择在发生任何映射之前对输入数组元素进行排序。 可以使用For-each转换的属性页来完成。 您可以在数组中指定要用于排序的字段。 您还可以指定将使用词法搜索还是数字搜索,以及对升序还是降序进行排序。 例如,假设您有一个目的地数组,其中每个目的地都有一个城市名称和一个国家名称。 假设您要基于城市名称按升序对列表进行排序。 您可以使用For-each转换的Properties页面来指定排序, 如图11所示。

图11.排序数组
排序数组

过滤数组

有时在处理数组输入时,您可能只想处理数组中的特定元素。 在这种情况下,您可以在“属性”视图的“基数”选项卡上指定适用的数组索引,也可以将过滤器表达式应用于转换。

基数

您可以使用基数来确定哪些数组索引将用作转换的输入。 您可以指定单个索引,索引范围或逗号分隔的索引列表。 表1显示了可接受的特殊字符。

表1.基数语法
字符 含义
用于指定值的范围。
分隔符以分隔索引和/或范围的列表
* 所有索引/直到数组结尾

表2显示了如何使用上述特殊字符指定基数的一些示例。

表2.基数语法示例
含义
1个 仅元素1
1:3 要素1至3
2:* 元素2及以上
1,3,5:* 元素1、3、5及以上

数组索引从1而不是0开始。

使用XPath表达式进行过滤

在使用输入数组时,可以在转换中使用过滤器表达式来从源数组中过滤所需的元素。 在这种情况下,过滤器表达式确定从源数组中选择了哪些元素。 编写过滤器表达式以返回供For-each操作的节点集。 为了返回适当的节点集,将过滤器表达式写为谓词而不是true或false条件。 例如,假设您有一个旅行目的地数组,其中每个目的地都有一个城市名称和一个国家名称。 假设您要消除国家名称等于北极的任何目的地。 在这种情况下,可以将过滤器表达式添加到For-each转换中, 如图12所示。

图12.使用XPath表达式进行过滤
使用XPath表达式进行过滤

所有未设置为北极的目的地均会将其作为“每个”映射的输入。 设置为北极的目的地将被忽略,并且不属于For-each映射输入的一部分。

嵌套数组

组优化为将数组转换为嵌套数组提供了支持。 例如,假设您有一个旅行目的地数组,列表中的每个目的地都有一个类别,以指示旅行目的地的类型。 类别可能包括海滩,冒险等等。 如果要从这些目标创建嵌套数组,其中类别构成顶级数组,而每个类别中的目标构成嵌套数组,则可以使用组转换。 图13显示了Group转换,将目的地按类别分组到一个嵌套数组中。 请注意,在图13的“属性”页面中的“组”转换中,类别字段被指定为分组条件。

图13.组映射
组映射

类似于本地映射,组是容器映射,除非存在定义如何对输入数组的每次迭代进行操作的嵌套映射,否则它不会产生任何结果。 因此,必须指定有关将源中的哪些字段映射到目标中的哪些字段的详细信息,以完成Group的实现。

当前没有任何转换可让您将嵌套数组取消分组为单个数组。 但是,您可以使用自定义XSLT转换将嵌套数组操纵为单个数组。 有关如何完成此操作的示例,请参见本文的“ 定制XSLT”部分。

自订

在某些情况下,您可能会发现没有适当的现成优化方案来执行正确填充目标所需的数据操作。 在这种情况下,您可以使用自定义转换。 以下各节说明了三种定制转换类型:定制XPath,定制XSLT和定制Java™。

自定义XPath

在某些情况下,可能需要使用XPath表达式或XPath表达式的组合,这些表达式不能作为内置函数优化使用。 在这种情况下,您可以编写自定义XPath表达式以获得所需的结果。 在编写XPath表达式时,自定义转换的输入可用作变量。 您可以使用以下语法引用它们: $<variablename>

例如,如果变换具有一个名为currentTemperature的输入元素,则可以使用$currentTemperature引用该元素。

有关在表达式中使用XPath运算符的示例,请考虑以下情形:要使用xsd:int类型的两个输入的总和来产生xsd:int结果。 使用连接到该转换的两个int输入创建一个Custom转换,然后使用如下表达式将两个输入相加: $inputx + $inputy

在XPath表达式输入字段中调用content-assist(使用CTRL + Space)将显示可用变量的列表以及可以轻松插入表达式的XPath函数的列表, 如图14所示。

图14. XPath内容辅助
XPath内容辅助

自定义XSLT

您可以使用XSLT实现自定义转换。 使用XSLT时,将调用外部文件中的命名模板以产生目标输出。 自定义转换的输入作为参数发送到自定义XSLT。 常见的XSLT模板存储在库中,并由许多映射共享。 自定义XSLT对于在目标中创建源中不存在的元素很有用。 通常,您可以使用Submap来完成此操作,但是在某些情况下,Submap无法使用。 使用Custom XSLT时要记住的一些事情是:

  • 默认情况下,“自定义”映射的目标元素将自动创建,被调用的模板仅填充目标元素的内容。 如果需要使用Custom XSLT创建整个目标元素(例如,要在目标元素上设置属性),则必须选中“ Custom XSLT属性”页面上的“ 在模板中包括目标元素”复选框。
  • 在定制XSLT模板中,如果需要来自输入节点之外的其他节点的数据来完成模板,则可以将该节点作为附加输入连接到“定制”变换。 另一种选择是使用绝对XPath表达式。

作为使用自定义XSLT的示例,请考虑源上存在嵌套数组的情况。 如图15所示,外部数组是类别的列表,每个类别都包含与类别匹配的旅行目的地的列表。 该图使用以下样本数据:

  • 旅行类别:海滩
    • 墨西哥阿卡普尔科
    • 古巴维拉德罗
    • 美国迈阿密
  • 旅行类别:冒险
    • 加拿大怀特霍斯
    • 美国大峡谷
图15.带有自定义XSLT转换的示例图
带有自定义XSLT变换的样本图

上面的定制转换将调用下面的XSLT模板,将每个类别传递给模板,如清单1所示。

清单1.带有参数的定制XSLT
  1. <xsl:template name="CategoriesToAvailableDestinations">
  2. <xsl:param name="category"/>
  3. <xsl:for-each select="$category/travelDestination">
  4. <availableDestination>
  5. <xsl:copy-of select="destination"/>
  6. <category><xsl:value-of select="../categoryName"/></category>
  7. <popularity><xsl:value-of select="popularity"/></popularity>
  8. </availableDestination>
  9. </xsl:for-each>
  10. </xsl:template>

该模板使用xsl:for-each从每个类别中提取目的地,如清单2所示。

清单2. travelDestination循环
<xsl:for-each select="$category/travelDestination">

该模板还基于嵌套数组的父类别在输出目标中设置类别值,如清单3所示。

清单3.父类别
<category><xsl:value-of select="../categoryName"/></category>

给定样本输入数据,清单4中显示了availableDestinations输出数组。

清单4.生成的输出XML
  1. <availableDestinations>
  2. <availableDestination>
  3. <destination>
  4. <cityName>Acapulco</cityName>
  5. <countryName>Mexico</countryName>
  6. </destination>
  7. <category>Beach</category>
  8. <popularity>8</popularity>
  9. </availableDestination>
  10. <availableDestination>
  11. <destination>
  12. <cityName>Veradero</cityName>
  13. <countryName>Cuba</countryName>
  14. </destination>
  15. <category>Beach</category>
  16. <popularity>7</popularity>
  17. </availableDestination>
  18. <availableDestination>
  19. <destination>
  20. <cityName>Miami</cityName>
  21. <countryName>United States</countryName>
  22. </destination>
  23. <category>Beach</category>
  24. <popularity>7</popularity>
  25. </availableDestination>
  26. <availableDestination>
  27. <destination>
  28. <cityName>Whitehorse</cityName>
  29. <countryName>Canada</countryName>
  30. </destination>
  31. <category>Adventure</category>
  32. <popularity>7</popularity>
  33. </availableDestination>
  34. <availableDestination>
  35. <destination>
  36. <cityName>Grand Canyon</cityName>
  37. <countryName>United States</countryName>
  38. </destination>
  39. <category>Adventure</category>
  40. <popularity>9</popularity>
  41. </availableDestination>
  42. </availableDestinations>

要继续该示例,请假定您实际上并不想将所有目的地类别都放到一个列表中,而是只想从一个类别中将目的地放到一个列表中。 让我们假设客户将让您知道他们感兴趣的目的地类别。 图16中的下显示了客户选择的旅行类别以及已传递到Custom XSLT转换中的归类目的地列表。

图16.带有自定义XSLT转换的示例图
带有自定义XSLT变换的样本图

上面的地图调用以下XSLT模板,仅从适用的类别中查找目的地,如清单5所示。

清单5. CategoriesToAvailableDestinations模板
  1. <xsl:template name="CategoriesToAvailableDestinations">
  2. <xsl:param name="category"/>
  3. <xsl:param name="customerTravelCategory"/>
  4. <xsl:for-each select="$category/travelDestination">
  5. <xsl:if test="../categoryName=$customerTravelCategory">
  6. <availableDestination>
  7. <xsl:copy-of select="destination"/>
  8. <category><xsl:value-of select="../categoryName"/></category>
  9. <popularity><xsl:value-of select="popularity"/></popularity>
  10. </availableDestination>
  11. </xsl:if>
  12. </xsl:for-each>
  13. </xsl:template>

在上面的示例中,请注意以下几点:

  • travelCateogory元素已作为“定制”转换的第二个输入添加,因此其值可用作定制模板中的参数。
  • 清单6中显示的以下If语句确保仅选择适当类别中的目的地。
清单6. customerTravelCategory条件
<xsl:if test="../categoryName=$customerTravelCategory">

注意 :每次为自定义XSLT引用XSLT文件时,都会将该XSLT文件的导入添加到映射文件中。 如果要将XSLT文件添加和删除到特定地图,则可能值得使用“属性”页面中的“ XSLT导入”选项卡清理未使用的导入。

在XSLT中使用内置扩展

XSL Transformation原语使用的XSLT处理器在WebSphere Process Server和WebSphere Enterprise Server Bus运行时中运行时,基于Apache Xalan-Java XSLTC处理器,该处理器提供EXSLT扩展功能,包括字符串函数,数学函数,设置函数,和日期和时间功能。 有关EXSLT函数的列表,请参见Apache XML Project

在某些情况下,IBM XSLTC处理器不同于Apache Xalan-Java XSLTC处理器,因此,上述所有功能可能都不可用。 以下示例显示了自定义XSLT模板中使用的ExstlString:split函数。 在该示例中,GetWeather服务返回了一个XML字符串,该字符串中的某处有一个要提取的温度值。 例如:

清单7.温度输出XML
  1. ...
  2. ...
  3. <Temperature> 55 F (13 C) </Temperature>
  4. ...
  5. ...
清单8. GetWeatherResultToCurrentTemperature XSL模板
  1. ...
  2. xmlns:str="http://exslt.org/strings"
  3. ...
  4. <xsl:template name="GetWeatherResultToCurrentTemperature">
  5. <xsl:param name="GetWeatherResult"/>
  6. <!-- Get all text after the <Temperature> tag in GetWeather output string -->
  7. <xsl:variable
  8. name="temp1"
  9. select="str:split($GetWeatherResult, '&lt;Temperature&gt;')[2]"/>
  10. <!-- Get only the text before </Temperature> in the already reduced string -->
  11. <xsl:variable
  12. name="temp2"
  13. select="str:split($temp1, '&lt;/Temperature&gt;')[1]"/>
  14. <!-- Remove leading and trailing white-space before returning the result -->
  15. <xsl:value-of select="normalize-space($temp2)"/>
  16. </xsl:template>

注意:

  • 在样式表上定义了str命名空间,如下所示: xmlns: str ="http://exslt.org/strings"
  • 使用两个字符串参数调用split函数,如下所示: select="str:split($GetWeatherResult, '&lt;Temperature&gt;')[2]"

使用库中的通用XSL文件

我们建议您将常见的XSL模板放在库项目中的自定义XSL文件中。 通过使用库,多个中介模块可以访问通用XSL模板。

将公共XSL文件导入位于中介模块中的XSL文件时,请使用xsltcl URI。 例如,如果中介模块中的XSL文件是MediationModule1 / xslt / MyMap-custom.xsl,而您要导入的XSL文件是/Library1/common/CommonXSLLibrary.xsl,则导入将是: <xsl:import href="xsltcl://common/CommonXSLLibrary.xsl"/>

URI中不包含库的名称Library1。

自定义Java

实现自定义转换的第三种方法是使用对静态Java方法的调用。 您可以使用Java调用来填充任何简单类型或复杂元素的值。 您可以将输入连接到Custom Java转换,并将这些输入用作方法参数。 输入可以是简单或复杂的类型。 当使用复杂类型输入作为方法参数时,相应的方法期望复杂类型数组的参数类型为org.w3c.dom.Node或org.w3c.dom.NodeList。 使用定制Java转换时,可以使用“定制”转换的“属性”页面选择所需的类和方法,以及将“定制”转换的输入映射到Java方法的参数。

为了说明Custom Java调用的基本用法,请考虑清单9中所示的示例。在中介流中,将进行对Web服务的调用,以检查特定目的地的天气。 气象服务返回XML结果,而目的地的温度被埋在该结果中。 静态Java方法用于解析XML数据,并且仅提取温度作为int值。

清单9. Web服务返回的XML输出
  1. <CurrentWeather>
  2. <Location>Toronto Pearson Int'L. Ont., Canada (CYYZ)
  3. 43-40N 079-38W 173M</Location>
  4. <Time>Oct 24, 2008 - 05:00 PM EDT / 2008.10.24 2100
  5. UTC</Time>
  6. <Wind>from the ESE (110 degrees) at 9 MPH (8 KT):0</Wind>
  7. <Visibility>15 mile(s):0</Visibility>
  8. <SkyConditions>overcast</SkyConditions>
  9. <Temperature>50 F (10 C)</Temperature>
  10. <DewPoint>41 F (5 C)</DewPoint>
  11. <RelativeHumidity>71%</RelativeHumidity>
  12. <Pressure>30.14 in. Hg (1020 hPa)</Pressure>
  13. <Status>Success</Status>
  14. </CurrentWeather>

假设您有兴趣提取温度的摄氏温度版本(对于上面的示例是21)。给定上述数据,清单10中所示的以下Java方法将通过在输出中找到<Temperature>标签来提取摄氏温度。 </温度>。

清单10. getCelsiusTemperature Java方法
  1. public static int getCelsiusTemperature(String originalWeatherReport) {
  2. int temperature = -99; // Error - Can't find temperature
  3. if (originalWeatherReport != null)
  4. {
  5. int temperatureStartIndex = originalWeatherReport
  6. .indexOf(TEMPERATURE_START_TAG);
  7. int temperatureEndIndex = originalWeatherReport
  8. .indexOf(TEMPERATURE_END_TAG);
  9. if ((temperatureStartIndex >= 0)
  10. && (temperatureEndIndex > temperatureStartIndex))
  11. {
  12. temperatureStartIndex = temperatureStartIndex
  13. + TEMPERATURE_START_TAG.length();
  14. String temperatureString = originalWeatherReport.substring(
  15. temperatureStartIndex, temperatureEndIndex);
  16. int startBracketIndex = temperatureString.indexOf('(');
  17. int endBracketIndex = temperatureString.indexOf(')');
  18. if (startBracketIndex >= 0 && endBracketIndex >= 0
  19. && (startBracketIndex < endBracketIndex))
  20. {
  21. String celsiusString = temperatureString.substring(
  22. startBracketIndex + 1, endBracketIndex);
  23. if (celsiusString.endsWith("C"))
  24. {
  25. celsiusString = celsiusString.substring(0,
  26. celsiusString.length() - 1);
  27. celsiusString = celsiusString.trim();
  28. try {
  29. double doubleValue = Double.parseDouble(celsiusString);
  30. temperature = (int) Math.round(doubleValue);
  31. } catch (NumberFormatException e) {
  32. }
  33. }
  34. }
  35. }
  36. }
  37. return temperature;
  38. }

若要在自定义转换中使用上述方法,请执行以下操作:

  • 确保包含映射文件的库或模块对包含包含方法的Java文件的项目具有依赖性。
  • 在适当的映射文件中创建Custom Java转换, 如图17所示。
    图17.自定义Java映射
    自定义Java映射
  • 在Custom Java转换的“常规属性”页面上,使用“类”字段旁边的“ 浏览”按钮浏览包含该方法的类。 在“选择类型”对话框中键入类名称时,可用选项的列表将更新为包括与键入的前缀匹配的类。
  • 在“方法”下拉框中,选择所需的方法。
  • 在参数部分中,选择适当的输入字段以映射到每个方法参数。 例如, 图18中的以下属性页将GetWeatherResult值引用为变量。
    图18. Custom Java映射属性页面
    自定义Java映射属性页面

在前面的示例中,Custom Java转换的输入和输出都是简单类型。 作为另一个示例,请考虑您要使用复杂类型输入数组在目标上填充复杂类型数组的情况。 Java方法将NodeList作为输入参数,并返回NodeList作为结果。

在此示例中,假设您在源端具有一个目标数组,并且想要在填充目标端的目标列表之前使用Java方法向列表中添加一些其他目标。 第一步是创建一个自定义Java类,它将执行以下操作:

  1. 生成其他目的地列表。
  2. 将现有目的地与其他目的地合并。
  3. 返回NodeList中的合并列表。

在此示例中,将创建DestinationCreationUtility类。 该类将包含清单11中所示的以下方法。

清单11. appendCreatedDestinations Java方法
  1. public static NodeList appendCreatedDestinations(NodeList
  2. arrayOfTravelDestinations)

此方法将接受TravelDestination节点的数组,并将解析这些节点以确定现有目的地的列表。 该方法会将现有的目的地转换为TravelDestination对象,以更轻松地将其与其他目的地列表合并,如清单12所示。

清单12. getAdditionalDestinations Java方法
public static ArrayList<TravelDestination> getAdditionalDestinations()

这是产生其他目的地列表的方法。 然后,您可以合并该列表和现有目的地列表,以创建TravelDestination对象的唯一列表,如清单13所示。

清单13. convertToNodeList Java方法
private static NodeList convertToNodeList(ArrayList<TravelDestination> allDestinations)

此方法将获取TravelDestination对象的列表并构建一个NodeList。 如清单14所示实现了convertToNodeList方法。

清单14. DestinationCreationUtility Java类
  1. import java.util.ArrayList;
  2. import javax.xml.parsers.DocumentBuilderFactory;
  3. import javax.xml.parsers.ParserConfigurationException;
  4. import org.apache.xpath.NodeSet;
  5. import org.w3c.dom.DOMException;
  6. import org.w3c.dom.Document;
  7. import org.w3c.dom.Element;
  8. import org.w3c.dom.Node;
  9. import org.w3c.dom.NodeList;
  10. import org.w3c.dom.Text;
  11. public class DestinationCreationUtility {
  12. ...
  13. private static NodeList convertToNodeList(
  14. ArrayList<TravelDestination> allDestinations) {
  15. NodeSet resultSet = new NodeSet();
  16. try {
  17. Document doc = DocumentBuilderFactory.newInstance()
  18. .newDocumentBuilder().newDocument();
  19. for (int i = 0; i < allDestinations.size(); i++) {
  20. TravelDestination next = allDestinations.get(i);
  21. Element nextAvailableDestination = doc.createElement("availableDestination");
  22. Element destinationElement = doc.createElement("destination");
  23. Element cityName = doc.createElement("cityName");
  24. Text cityNameText = doc.createTextNode(next.cityName);
  25. cityName.appendChild(cityNameText);
  26. Element countryName = doc.createElement("countryName");
  27. Text countryNameText = doc.createTextNode(next.countryName);
  28. countryName.appendChild(countryNameText);
  29. Element categoryElement = doc.createElement("category");
  30. Text categoryText = doc.createTextNode(next.category);
  31. categoryElement.appendChild(categoryText);
  32. Element popularityElement = doc.createElement("popularity");
  33. Text popularityText = doc.createTextNode(next.popularity + "");
  34. popularityElement.appendChild(popularityText);
  35. destinationElement.appendChild(cityName);
  36. destinationElement.appendChild(countryName);
  37. nextAvailableDestination.appendChild(destinationElement);
  38. nextAvailableDestination.appendChild(categoryElement);
  39. nextAvailableDestination.appendChild(popularityElement);
  40. resultSet.addElement(nextAvailableDestination);
  41. }
  42. } catch (DOMException e) {
  43. throw new org.apache.xml.utils.WrappedRuntimeException(e);
  44. } catch (ParserConfigurationException e) {
  45. throw new org.apache.xml.utils.WrappedRuntimeException(e);
  46. }
  47. return resultSet;
  48. }
  49. ...
  50. }

为了完成任务,一旦创建了DestinationCreationUtility类,就创建了一个使用Custom Java变换将源目的地映射到目标目的地的映射, 如图19所示。

图19.带有属性集的定制Java映射
具有属性集的自定义Java映射

调试自定义Java调用

当具有使用自定义Java调用的映射时,可以调试该映射在服务器上运行时正在调用的Java。 使用“测试图”视图或使用Integration Test Client在本地测试图文件时,在Java代码中设置断点将没有任何影响。 但是,如果您正在使用Integration Test Client进行组件测试,并且服务器正在Debug模式下运行,则您在称为Java方法中设置的断点将导致执行停止,因此您可以逐步执行Java方法。

使用通配符

通配符是一种允许XML模式定义灵活的机制。 由于通配符的结构未在XML模式中定义,因此XML映射编辑器无法自动显示通配符的结构。 从V7.0.0开始,XML映射编辑器提供了将通配符转换为具体类型的支持,从而可以显示结构并轻松进行映射。 在中介流中工作时,进行转换的另一种方法是在使用XSL转换原语之前使用“设置消息类型”原语。 设置消息类型原语将允许您指定用于通配符的具体类型。

识别通配符

基于XML架构定义,通配符可以以以下三种形式出现:

<any>通配符

在这种情况下,期望具有任何名称和任何类型的元素。 在XML映射编辑器中,通过使用

任何图标
图标,名称any和在type列中没有指定的类型, 如图20所示。
图20. XML Schema任何元素
XML Schema任何元素

在上面的示例中,<any>通配符也是可重复的,在这种情况下,目标可以包含具有任何名称和类型的元素数组。 与任何其他字段一样,基数列将指示<any>通配符是否可重复。

<anyAttribute>通配符

在这种情况下,将接受具有任何名称和任何值的零个或多个属性。 在XML映射编辑器中,<anyAttribute>通配符通过使用

anyAttribute图标
图标,名称为anyAttribute,并且在type列中没有指定的类型, 如图21所示。
图21. XML Schema any属性
XML模式的任何属性

anyType类型

在这种情况下,应使用具有指定名称的元素,但是该元素可以是任何类型。 以下是图22的XML映射编辑器中显示的名为related的anyType Type元素的示例。

图22. XML模式anyanyType
XML模式anyanyType

当目标需要anyType时,建议使用xsi:type属性设置结果目标元素中的类型。 运行时在处理时使用xsi:type属性。 如果未为anyType目标设置xsi:type属性,则可能会发生故障。

从源中的通配符映射

如果您的源是通配符或具有anyType类型,则可以使用以下方法之一将输入的内容映射到目标:

新图标
当您知道源将始终包含相同的类型或相同的全局元素/属性时,首选转换方法。 通过右键单击通配符并选择“投射”菜单操作来完成投射。

<any>通配符 :如果您可以将潜在的<any>通配符输入的范围缩小到一组全局元素,则可以将输入<any>通配符转换为每个潜在的全局元素。 转换后,只有在运行时相应的全局元素实际上是输入文档的一部分时,才会运行从转换的全局元素创建的转换。

<anyAttribute>通配符 :如果您可以将潜在的<anyAttribute>通配符输入的范围缩小到一组全局属性,则可以将输入的<anyAttribute>通配符转换为每个潜在的全局属性。 转换后,只有在运行时相应的全局属性实际上是输入文档的一部分时,才会运行从转换的全局属性创建的转换。

anyType类型 :如果您可以将潜在输入类型的列表缩小为一组具体类型,则可以将anytType输入元素强制转换为每种潜在具体类型。 转换后,只有在运行时相应类型实际上是输入文档的一部分时,才会运行从转换类型创建的转换。

移动

如果不需要操纵输入,则可以使用“移动”变换将精确的输入复制到目标文档。

<any>通配符 :如果要精确复制源元素,则可以使用Move转换将<any>通配符表示的源元素移动到目标。 为了在运行时有效,源元素的名称和类型将需要与目标所需的名称和类型匹配。

<anyAttribute>通配符 :您不能使用Move从<anyAttribute>通配符源进行映射。

anyType类型 :如果目标元素也具有anyType类型,则只能将Move变换与具有anyType类型的源元素一起使用。 不支持从具有anyType类型的源元素移动到具有具体类型的目标元素。

子图

如果确定所需强制转换的逻辑复杂且可恢复,请考虑使用Submap。

<any>通配符 :如果源中有一个<any>通配符,其中包含填充目标元素所需的数据,但与目标元素所需的元素结构不完全匹配,则可以使用Submap进行映射这两个元素,或这些元素的两种类型。 创建Submap时,将期望的元素或源类型指定为Submap输入。 设置子图输入后,输入的完整结构将显示在子图中,并且适当的源字段将映射到适当的目标字段。

<anyAttribute> wildcard : Submaps are not supported for <anyAttribute> wildcard sources.

Custom

When a Cast, Move, or a Submap cannot be used to achieve the desired results, you can use a Custom XPath, Custom XSLT, or Custom Java transform with a wildcard input. A Custom transform allows you to dissect a source wildcard in any form you want. A Custom transform also allows you to map from two separate wildcard sources into a single target.

When using Custom transforms to map from an <anyAttribute> wildcard, it is recommended that you use the parent of the <anyAttribute> wildcard as the transform input. This allows you to access the attributes by name or position. For example, if you had a Custom XPath transform with an input from an element named luggage and you wanted to access an attribute named passengerName to assign to the output attribute, you could use a Custom XPath transform with an XPath expression such as $luggage/@passengerName .

Mapping to a wildcard in the target

In cases where you have a target that is a wildcard or has an anyType type, you can use one of the following methods to map into the wildcard target.

Cast

New icon Casting is the preferred method when you know that the target will always contain the same types or same global elements or attributes. Casting is done by right-clicking the wildcard and selecting the Cast menu action.

<any> wildcard : Casting allows you to cast an <any> wildcard to one or more specific global elements. If you are certain that the same global element or elements will always be used to populate the target <any> wildcard, you can cast the <any> wildcard to each of the expected global elements. When the target is expecting only a single element and there are multiple cast global elements, we recommend that you create mappings at the top level of the cast global elements. For example, consider the case where a singleton <any> wildcard is cast to two different global elements, GlobalElementA and GlobalElementB. The intention is that, depending on the existence of certain inputs, only one of GlobalElementA or GlobalElementB is created in the target at runtime. To ensure that only one of the global elements is created at runtime, ensure the following:

  • Only the inputs to one of the global elements are present in the input XML document at runtime.
  • The target global elements are mapped at the top most level.

Figure 23 illustrates mapping to the top most level, the following mappings are created at the top most level of the cast global elements and is correct.

Figure 23. Valid Cast mapping
Valid Cast mapping

The following mappings are not created at the top most level and lead to empty elements being created at runtime, regardless of the existence of the input elements. The following is incorrect, shown in Figure 24.

Figure 24. Invalid Cast mapping
Invalid Cast mapping

<anyAttribute> wildcard : Casting allows you to cast an <anyAttribute> wildcard to a one or more specific global attributes. If you are certain that the same global attributes will always be used to populate the target <anyAttribute> wildcard, you can cast the <anyAttribute> wildcard to the each of the expected global attributes.

anyType type : If the type of the target anyType is known, the preferred method for working with the anyType is to cast it to a concrete type.

Move

<any> wildcard : If there is a source element which is exactly the element you want to populate the target with, a Move will copy the element from the source to the target <any> wildcard.

When mapping to an <any> wildcard in the target, it is your responsibility to ensure that namespace and processing constraints are not violated. When you select an <any> wildcard in the target column, the Properties view will display the namespace and processing constraints, but there is no validation check to ensure the constraints are not violated.

<anyAttribute> wildcard : If the attributes to be included in the target appear with the desired name and values somewhere in the source, you can use one or more Move transforms to copy the attributes from the source to the target. In cases where the attribute does not exist in the source or the attribute name needs to be changed, a Custom transform is required. Figure 25 shows an example how multiple source attributes are mapped to an <anyAttribute> wildcard on the target.

Figure 25. Multiple source attributes mapping to a target <anyAttribute>
Multiple source attributes mapping to a target <anyAttribute>

anyType type : If there is a source element, which is the exact type that you want to populate the target, a Move will copy the elements content from the source to the target. The Move transform automatically adds the recommended xsi:type attribute to the target element so that the type is correctly recognized at runtime.

Submap

In cases where you have complex logic that determines what types are used and you want that logic to be reusable, you can use a Submap.

<any> wildcard : When mapping to an <any> wildcard in the target using a Submap, it is your responsibility to ensure that namespace and processing constraints are not violated. When you select an <any> wildcard in the target column, the Properties view will display the namespace and processing constraints, but there is no validation check to ensure that the constraints are not violated.

<anyAttribute> wildcard : You cannot use a Submap cannot to populate an <anyAttribute> wildcard in the target.

anyType type : When used with anyType type targets, a Submap transform uses the correct element name for the target element and also adds the recommended xsi:type attribute required to ensure that the target element is correctly recognized at runtime.

Custom

When a Cast, Move transform, or Submap transform is not applicable, you can use a Custom XPath, Custom XSLT, or Custom Java transform to construct the appropriate elements or attributes for the target. If using a Custom transform to map to an element having an anyType type, keep in mind that you need to set the xsi:type attribute for that element.

Working with derived types defined through extension and restriction

In cases where a base type has been extended or restricted, you can use casting to display the derived structure in the source or target. In the case where the input contains a base type of a derived type, you can cast that base type to any of its derived types as shown in Figure 26 .

Figure 26. Casting derived types
Casting derived types

In the above example, Address is the base type and is the type that is defined as the type for field2 in the schema. In this case, field2 has been cast to both USAddress and UKAddress, which are both extended types of type Address.

To prevent undesirable duplicate or empty elements from being created in the target at runtime, we recommend that you follow the following conventions:

  • Once a source or target element has been cast to derived types, we recommend that you only create mappings to and from the derived types and not to the base type.
  • On the target, always create mappings to the top level of the optional element. For example, suppose that you have an singleton element of type Address in the target, that element has been cast to two derived types, USAddress and UKAddress. The intention in this case is that, based on the existence of certain inputs, only one of the derived types will appear in the target document. To ensure that a target is only created in the case where the mapped inputs are present in the input document, map to the top level before mapping any children. Figure 27 illustrates top level mappings and is correct.
    Figure 27. Valid derived type casting
    Valid derived type casting

    Figure 28 illustrates mappings directly to the children of cast elements and is incorrect.
    Figure 28. Invalid derived type casting
    Invalid derived type casting

Casting is done by right-clicking a field in the source or target and selecting the Cast menu action. Only valid derived types are shown when you invoke the casting action. If there are no valid derived types for the selected field, a dialog is displayed to indicate no types are available. If the desired types are not found, ensure that the desired derived types are included in a referenced project.

Working with choice elements

XSD model groups, such as xsd:sequence and xsd:choice, are not shown by default within the XML Mapping editor. Changing the view preferences to show groups will show the XSD model group information, allowing you to identify where choice group elements exist. Click the Open preferences button (

Open preferences button ) on the local toolbar to change the view preferences.

You cannot directly map the choice element, but you can map the elements contained within a choice group. An instance document can only contain one of the elements contained within a non repeatable choice model group at any time; 不太多。 Therefore, when creating transforms from members of a non-repeatable choice group, only the transforms connected to those member elements, which exist in the runtime instance document, will get executed. Any transforms connected to the other elements are ignored.

When creating transforms, which target choice group elements, ensure that the mapping logic only produces one of the choice group elements. Unexpected results will occur if multiple elements in a choice group get set, as the generated XSL will try to create a valid XML output document. Using If, Else If, and Else transforms, or using Custom XPath, Custom XSLT, or Custom Java transforms to ensure that only one element in a choice group gets created will ensure that the expected results are achieved during the execution of the map.

Working with substitution groups

Substitution groups are not explicitly shown by default in the XML Mapping Editor. However, you can identify the head elements contained within a substitution group by means of the following icon on an element:

Substitution group icon
。 Substitution groups can be explicitly shown by changing the view preference to show groups. Click the Open preferences button (
Open preferences button ) on the local toolbar to change the show groups preference.

Like the actual xsd:sequence and xsd:choice elements that are shown, you cannot directly map sbstitution group nodes, but you can map the elements contained within a substitution group. Similarly, like choice elements, it is important to remember that an instance document can only contain one member of the substitutable elements at a time; 不太多。

Unlike the Business Object Mapper, which bases its mappings on generalizations, the XSLT Mapper will only execute transforms that match the exact element in the instance document during execution. Therefore, creating a "general" transform on the head element of a substitution group to handle any derived element types that may exist in instance document will not handle all cases. Rather, if each element is expected to be transformed, each must be involved in a specific transform to handle the unique case. This method allows certain elements contained in a substitution group to be filtered (by not moving data over to the target), if desired.

When creating transforms which target substitution group members, ensure that the mapping logic only produces one of the members. Unexpected results will occur if multiple elements in a substitution group get set, as the generated XSL will try to produce a valid XML output document.

SOAP headers

The following section explains some of the common use cases that occur when working with SOAP headers. The value element in the SOAP header element is an anyType type element named value and can be set using the methods explained in the Mapping to a wildcard in the target section. The easiest method to work with the value element is to cast it to an element of the desired output type.

Another case that can occur is when you want to do a conditional mapping based on the SOAP header name. In this case, you can create If, Else If and Else mappings. For examples of how to do the if-else logic, see Conditional mapping in Part 1 of this series.

SOAP-encoded arrays

In cases where your source or target contains a SOAP encoded array, you may encounter a case where you want to move array elements from a SOAP encoded array to a standard array or vice versa. The XML Mapping editor does not recognize the type of the elements within a SOAP encoded array and will display the elements as an array of <any> wildcard elements. The case of converting to or from a SOAP encoded array is covered in this section.

Case 1. Copying from a SOAP-encoded source array to a regular target array

In this case, you can use a For-each and a Submap mapping. The For-each is used to iterate over each of the <any> wildcard elements in the source array and the Submap is then used to cast those elements to the desired type. For example, consider that you have a SOAP encoded array of Destination elements on the source that you want to use to populate a regular array of Destination elements on the target as shown in Figure 29 .

Figure 29. SOAP-encoded array Foreach mapping
SOAP-encoded array Foreach mapping

Within the For-each mapping, a Submap mapping is used to map the <any> wildcard elements, which are actually Destination elements in this example, to Destination elements as shown in Figure 30 .

Figure 30. SOAP-encoded array Submap mapping
SOAP-encoded array Submap mapping

The Submap transformation above calls a Submap that has Destination as both the source and target type.

Case 2. Copying from a regular source array to a SOAP-encoded target array

The case of going to a SOAP array requires writing custom XSLT to create the array elements for the SOAP array. The custom XSLT must do the following to create a conforming SOAP array:

  • Use the name item for each array element. This allows the SOAP array contents to be viewed while working in the Integration Test Client. For example: < item xsi:type="in:Destination"> .
  • Use the xsi:type attribute on each of the items within the SOAP array. Otherwise, a runtime error occurs since the type of the array elements cannot be determined: <item xsi:type ="in:Destination"> .

To demonstrate the scenario of converting a regular array to a SOAP encoded array, assume that you have a list of Destination elements in the source that you want to use to populate a SOAP encoded list of Destinations on the target. The Custom transform is created in the map as shown in Figure 31 .

Figure 31. SOAP-encoded array Custom mapping
SOAP-encoded array Custom mapping

The target of the Custom XSLT transform is the repeatable <any> wildcard. On the Custom XSLT Properties page, the Include target element within the template checkbox is checked, which allows you to create the <any> wildcard array elements entirely in the Custom XSLT. The outer shell of the target element is always created by default on a Custom XSLT transform, unless you select the Include target element within the template checkbox. Listing 15 shows the custom XSLT.

Listing 15. DestinationToSOAPDestination XSL template
  1. <xsl:template name="DestinationToSOAPDestination">
  2. <xsl:param name="destination" />
  3. <xsl:for-each select="$destination">
  4. <item xsi:type="in:Destination">
  5. <cityName>
  6. <xsl:value-of select="cityName" />
  7. </cityName>
  8. <countryName>
  9. <xsl:value-of select="countryName" />
  10. </countryName>
  11. </item>
  12. </xsl:for-each>
  13. </xsl:template>

Advanced tips and tricks

Creating new target nodes

New nodes can be introduced into the target in a number of ways. One such way is to apply a Submap or Custom transform to a target node that is replaceable (for example, a wildcard, a derivable type, or a substitution group member). You can then replace that target node with an appropriate node or set of nodes in the specific Submap or Custom code. Alternatively, you can introduce new nodes directly into the mapping editor by substituting one substitution group member for another, or by casting a base type to one or more of its derived types. For more information, see the Custom and Working with types defined through extension and restriction sections.

Ensuring a complete target XML document

When you create a map using the XML Mapping Editor, there is no automatic validation to ensure that the mappings you created will produce a complete target XML document. The validation tries to ensure that each target field is populated with valid data, but it does not catch cases where a target field that is required is not populated at all. If a required target field is not mapped, the resulting target element is not valid according to its schema. You can identify a required target field by looking at the cardinality column for the target. In cases where the cardinality is shown as [1..1] or [1…n] or [1…*], the field is required. If a field is required, and the parent of that field is present in the output, the required field must also be present in the output. It can be tricky to determine if a field must be present in the output document because it depends on all the fields ancestors. For example, if all the fields ancestors are required, then the field is required. As another example, if the field is required, but the fields parent is optional and is not mapped, the field does not need to present in the output document.

Once you determine that a field is required and must be present in the output XML document, ensure the following:

  • There is a mapping to the required field.
  • If the required field is mapped from a mapping with an optional field as the input, ensure that a second conditional mapping is used to cover the case where the source field is not present in the input XML. Basically, this is the case where you have used an optional source to populate a required target. In such a case, you need a contingency plan for cases where the source is not present. To create a contingency mapping, consider using If and Else mappings to ensure that at least one mapping to the required target will always occur, regardless of optional inputs. For more information on using conditions on mappings, see Conditional mappings in Part 1 of this series.

Hints for mapping to target head elements

Occasionally, you will find that it is necessary, or at least beneficial, to map to a target head element that is the top level target element within a map or a nested map. Figure 32 and Figure 33 are two examples of head elements within their respective maps or nested maps.

Figure 32. Root head element
Root head element
Figure 33. Nested head element
Nested head element

Mappings to a head element are not supported in all cases. The following are general rules for mapping to head element targets:

  • In general, container mappings (If, Else if, Else, Local, For-each, Merge and Append) are not allowed to head element targets. The one exception is inside an If, Else if, or Else mapping, in which case you can use Local, Foreach, Merge and Append.
  • Move, Convert, Submap, Custom, Substring, Normalize, and Concat mappings are allowed to head element targets when applicable.
  • When using Append, mappings to head element targets are automatically created. Those generated mappings are the only head element mappings that are permitted within the Append.
  • Submap and Custom are two transforms often used to map to a head element target because they allow for the reuse. When using a Submap to target a head element target, the Submap must be a type mapping.

Ensuring a namespace prefix used in Custom XSLT is recognized in the output XML

There is a known problem:

  • An XSL file (such as the one generated for a .map file) calls another XSL template (such as a Custom XSLT mapping).
  • The calling XSL file uses the exclude-result-prefixes attribute to exclude certain prefixes. 例如:
    1. xmlns:in="http://TravelDestinationsLibrary"
    2. ...
    3. exclude-result-prefixes="in xalan"
  • The called XSL file re-uses the excluded prefix, but does not declare it to be excluded. 例如:
    1. xmlns:in="http://TravelDestinationsLibrary"
    2. ...
    3. exclude-result-prefixes="xalan"
  • The output XML file will not contain the namespace declaration required by the called XSL file. Usage of that namespace will cause errors at runtime because it is not recognized.

The problem will not occur during local map tests nor will it occur at runtime if the server is running in debug mode. The problem only occurs when running the server in non-debug mode. A common scenario where this can happen is when using the xsi:type attribute in Custom XSLT. There is a workaround to ensure the namespace gets included. The workaround is explained using the same example that was used to explain the scenario of mapping from a regular array to a soap encoded array. In this case, Custom XSLT is used and the Custom XSLT uses the xsi:type attribute, as shown in Listing 16.

Listing 16. DestinationToSOAPEncodedDestinationArray XSL template
  1. <xsl:template name="DestinationToSOAPEncodedDestinationArray">
  2. <xsl:param name="destination" />
  3. <xsl:for-each select="$destination">
  4. <item xsi:type="in:Destination">
  5. <cityName>
  6. <xsl:value-of select="cityName" />
  7. </cityName>
  8. <countryName>
  9. <xsl:value-of select="countryName" />
  10. </countryName>
  11. </item>
  12. </xsl:for-each>
  13. </xsl:template>

The item element is declared with an xsi:type attribute that uses the in namespace, as shown in Listing 17.

Listing 17. item xsi:type attribute
<item xsi:type="in:Destination">

The above XSLT will produce the correct result while testing locally, but will fail at runtime if the server is not running in debug mode because the in namespace will not be recognized. To resolve the problem, the namespace declaration is added to the element tag using <xsi:text>, as shown in Listing 18.

Listing 18. DestinationToSOAPEncodedDestinationArray XSL template
  1. <xsl:template name="DestinationToSOAPEncodedDestinationArray">
  2. <xsl:param name="destination" />
  3. <xsl:for-each select="$destination">
  4. <xsl:text disable-output-escaping="yes">
  5. <item xmlns:in="http://TravelDestinationsLibrary" xsi:type="in:Destination">
  6. </xsl:text>
  7. <cityName>
  8. <xsl:value-of select="cityName" />
  9. </cityName>
  10. <countryName>
  11. <xsl:value-of select="countryName" />
  12. </countryName>
  13. <xsl:text disable-output-escaping="yes">
  14. </item>
  15. </xsl:text>
  16. </xsl:for-each>
  17. </xsl:template>

The item elements start and end tags are wrapped with nxsi:text to force the inclusion of the in namespace declaration.

Organizing imports

New icon When you add a Custom XSLT, Custom Java, or Lookup transform to a map, a corresponding import for the referenced XSLT or Java file is added to the map. If the transform that caused the import to be added is later removed, the import is not automatically removed. To keep imports organized, you can view all imports and manually remove unused imports using the map file property pages. To access the properties for a map file, select the map background canvas while the file is open in the editor and then open the Properties view. Selecting the background of the map ensures that no specific element or transform is selected and the properties shown will apply to the map file, rather than a specific element in the map. In the properties view, you can use the XSLT Imports and Java Imports pages to work with the map file imports.

There is also a properties page called Namespaces, which allows for custom prefixes to be defined for a given namespace. You can use this in cases where prefixes are not bound to a specific namespace at runtime, or if there is a need to use a constant prefix throughout the application for a given namespace.

结论

In this article, you learned how to work with complex arrays, custom transformations with Java, XSLT templates and XPath, along with best practices for handling XML schema any, anyType and derived types. The article also discussed how to handle SOAP headers and also SOAP encoded arrays within WebSphere Enterprise Service Bus. These key mapping skills are an important part in creating more complex XMl maps within WebSphere Integration Developer.


翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/1003_spriet2/1003_spriet2.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/306300
推荐阅读
相关标签
  

闽ICP备14008679号