我从发送更改命名空间的子系统接收 XML 消息。 系统似乎会根据是否需要增加命名空间上的计数器。 我不知道如何在 SAP 中处理这个问题。
例如,它可能会向我发送以下内容:
<?xml version="1.0"?>
<topTag xmlns:ns1="xsd/namespacesForBoxes"
xmlns:ns2="xsd/namespacesForCartons"
xmlns:ns3="xsd/namespacesForPallets">
<ns1:container>
<ns1content/>
</ns1:container>
<ns2:container>
<ns2:content/>
</ns2:container>
<ns3:container>
<ns3:content/>
</ns3:container>
</topTag>
到目前为止还不错,但如果不需要第二个元素,它会将托盘的计数器设置为 2,如下所示:
<?xml version="1.0"?>
<topTag xmlns:ns1="xsd/namespacesForBoxes"
xmlns:ns2="xsd/namespacesForPallets">
<ns1:container>
<ns1content/>
</ns1:container>
<ns2:container>
<ns2:content/>
</ns2:container>
</topTag>
当然,
<content>
标签将根据我这边的命名空间保存不同的值,因此转换将失败,因为它“硬编码”了预期的命名空间。
有没有办法通过简单的转换来实现这一点? 该结构相当大,因此通过代码动态转换是不可行的。 或者有没有办法用其他转换技术来做到这一点?
追问:这正常吗? 对我来说,这似乎是一件非常疯狂的事情,如果不需要命名空间,他们不应该切换名称。这使得将数据追溯到字符串变得非常困难。
正如 Siebe Jongebloed 已经指出的那样,XML 文档的使用者永远不应该使用命名空间前缀(如
ns1
),而应使用命名空间 URI(如 xsd/namespacesForBoxes
)。
简单转换遵循此规则并比较命名空间 URI,而不是前缀,如以下示例所示:
<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates"
xmlns:ddic="http://www.sap.com/abapxml/types/dictionary"
xmlns:ns1="namespace_uri">
<tt:root name="ROOT" type="ddic:SCARR"/>
<tt:template>
<ns1:Airline>
<tt:value ref=".ROOT.CARRID"/>
</ns1:Airline>
</tt:template>
</tt:transform>
当您使用这个简单的转换将 ABAP 转换为 XML 时,您将获得命名空间前缀
ns1
。但是您可以交换 XML 文档中的名称空间前缀,并且仍然使用相同的简单转换将 XML 转换回 ABAP:
data: scarr type scarr,
xmlstring type string.
scarr-carrid = 'XX'.
call transformation ...
source root = scarr
result xml xmlstring.
write / xmlstring.
replace all occurrences of 'ns1' in xmlstring with 'ns2'.
call transformation ...
source xml xmlstring
result root = scarr.
write / scarr-carrid.
Heiko 之前的答案是正确的,简单的转换可以处理命名空间,我的解决方案所缺少的(除了缺乏命名空间处理之外)是条件检查。
如果您有三个名称空间,并且它们可能会更改数字,因为并非每个转换都需要所有名称空间,您需要使它们在转换中成为“可选”,如下所示:
<tt:template>
<top_element
xmlns:ns1="xsd/namespacesForBoxes"
xmlns:ns2="xsd/namespacesForCartons"
xmlns:ns3="xsd/namespacesForPallets">
<tt:namespace name="ns1"/>
<tt:namespace name="ns2"/>
<tt:namespace name="ns3"/>
<tt:cond s-check="not-initial(ref('.telegram.BOX_ID'))">
<ns1:container>
<tt:attribute name="box-id" value-ref=".telegram.BOX_ID"/>
</ns1:container>
</tt:cond>
<tt:cond s-check="not-initial(ref('.telegram.CARTON_ID'))">
<ns2:container>
<tt:attribute name="carton-id" value-ref=".telegram.CARTON_ID"/>
</ns2:container>
</tt:cond>
<tt:cond s-check="not-initial(ref('.telegram.PALLET_ID'))">
<ns3:container>
<tt:attribute name="pallet-id" value-ref=".telegram.PALLET_ID"/>
</ns3:container>
</tt:cond>
</top_element>
</tt:template>
这适用于我的测试报告:
TYPES: BEGIN OF ts_test,
box_id TYPE char10,
carton_ID TYPE char10,
pallet_ID TYPE char10,
END OF ts_test.
DATA(lv_res1) = VALUE ts_test( ).
DATA(lv_res2) = VALUE ts_test( ).
CONCATENATE
'<top_element '
'xmlns:ns1="xsd/namespacesForBoxes" '
'xmlns:ns2="xsd/namespacesForCartons" '
'xmlns:ns3="xsd/namespacesForPallets">'
'<ns1:container box-id="BOX"/>'
'<ns2:container carton-id="CARTON"/>'
'<ns3:container pallet-id="PALLET"/>'
'</top_element>'
INTO DATA(lv_trans1)
RESPECTING BLANKS.
CONCATENATE
'<top_element '
'xmlns:ns1="xsd/namespacesForBoxes" '
'xmlns:ns2="xsd/namespacesForPallets">'
'<ns1:container box-id="BOX"/>'
'<ns2:container pallet-id="PALLET"/>'
'</top_element>'
INTO DATA(lv_trans2)
RESPECTING BLANKS.
CALL TRANSFORMATION z_namespace_test
SOURCE XML lv_trans1
RESULT telegram = lv_res1.
CALL TRANSFORMATION z_namespace_test
SOURCE XML lv_trans2
RESULT telegram = lv_res2.
感谢您的投入!