目前我在ECC的系统找到两种实现XML解析的办法,第一种是通过strans创建转化例程,然后在程序中调用转化例程来转化xml,第二种是调用方法按照node解析xml。
要转化的xml文件demo如下
<?xml version="1.0" encoding="Windows-1252"?>
<PPSExport Version="1.1">
<ProductionOperationFeedback>
<Operation OrderNo="600001099">
<OperationNo>0010</OperationNo>
<PartNo>210402000001</PartNo>
<WorkPlace>TruLaserCenter7030-1</WorkPlace>
<CostCenter />
<TimeStamp>21.06.2023 09:10:21</TimeStamp>
<ReturnType>30</ReturnType>
<ProcessedParts>3</ProcessedParts>
<ScrapParts>0</ScrapParts>
<MissingParts>0</MissingParts>
<TargetProcessingTimePerPiece>0.35</TargetProcessingTimePerPiece>
<ProcessingTime>3.4500</ProcessingTime>
<SetupTime>0.0000</SetupTime>
<MeasuringTime>0.0000</MeasuringTime>
<OperationStart>21.06.2023 09:09:45</OperationStart>
<OperationEnd>21.06.2023 09:10:21</OperationEnd>
<PartWeight>3.93622</PartWeight>
<PartArea>0.41892516</PartArea>
<PartLength>1210.00000</PartLength>
<PartWidth>490.60000</PartWidth>
<Assembly>100260031100</Assembly>
<DataExt />
<OrderNoExt />
<CollectiveOrder>10000176</CollectiveOrder>
<ErpID />
<QuantityReports>
<QuantityReport>
<ReportingTime>21.06.2023 09:10:21</ReportingTime>
<ProcessedParts>3</ProcessedParts>
<ScrapParts>0</ScrapParts>
<MissingParts>0</MissingParts>
<BatchNo>123456</BatchNo>
<WorkPlace>TruLaserCenter7030-1</WorkPlace>
<ReportedBy>0101????</ReportedBy>
<Terminal>LAP361347</Terminal>
</QuantityReport>
</QuantityReports>
<Consumption>
<ResourceConsumption ResourceName="300102010012" ResourceType="20">
<ResourceDescription>300102010012</ResourceDescription>
<ResourceNote>DC01-012 3000x1250</ResourceNote>
<ResourceCategory />
<Consumption>3.75000</Consumption>
<UnitOfConsumption>m2</UnitOfConsumption>
<Rawmaterial>300102010012</Rawmaterial>
<Dimensions>
<Length>3000.00000</Length>
<Width>1250.00000</Width>
<Thickness>1.20000</Thickness>
<Unit>mm</Unit>
</Dimensions>
</ResourceConsumption>
</Consumption>
</Operation>
</ProductionOperationFeedback>
</PPSExport>
转化的结构定义如下
types: begin of ty_report,
reportingtime type string,
processedparts type string,
scrapparts type string,
missingparts type string,
batchno type string,
workplace type string,
reportedby type string,
terminal type string,
end of ty_report.
types: begin of ty_reports,
quantityreport type ty_report,
end of ty_reports.
types: begin of ty_dimensions,
length type string,
width type string,
thickness type string,
unit type string,
end of ty_dimensions.
types: begin of ty_resourceconsumption,
* resourcename TYPE string,
* resourcetype TYPE string,
resourcedescription type string,
resourcenote type string,
resourcecategory type string,
consumption type string,
unitofconsumption type string,
rawmaterial type string,
dimensions type ty_dimensions,
end of ty_resourceconsumption.
data: lt_resourceconsumption type table of ty_resourceconsumption,
ls_resourceconsumption type ty_resourceconsumption.
types: begin of ty_resourceconsumptions,
resourceconsumption like lt_resourceconsumption,
end of ty_resourceconsumptions.
types: begin of ty_order,
orderno type string,
operationno type string,
partno type string,
workplace type string,
costcenter type string,
timestamp type string,
returntype type string,
processedparts type string,
scrapparts type string,
missingparts type string,
targetprocessingtimeperpiece type string,
processingtime type string,
setuptime type string,
measuringtime type string,
operationstart type string,
operationend type string,
partweight type string,
partarea type string,
partlength type string,
partwidth type string,
assembly type string,
dataext type string,
ordernoext type string,
collectiveorder type string,
erpid type string,
quantityreports type ty_reports,
consumption type ty_resourceconsumptions,
end of ty_order.
方法一:STRANS
在事务码STRANS中创建转化例程:
strans代码如下:
<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates">
<tt:root name="ROOT"/>
<tt:template>
<PPSExport Version="1.1">
<ProductionOperationFeedback>
<Operation>
<OrderNo>
<tt:value ref="ROOT.ORDERNO"/>
</OrderNo>
<OperationNo>
<tt:value ref="ROOT.OPERATIONNO"/>
</OperationNo>
<PartNo>
<tt:value ref="ROOT.PARTNO"/>
</PartNo>
<WorkPlace>
<tt:value ref="ROOT.WORKPLACE"/>
</WorkPlace>
<CostCenter>
<tt:value ref="ROOT.COSTCENTER"/>
</CostCenter>
<TimeStamp>
<tt:value ref="ROOT.TIMESTAMP"/>
</TimeStamp>
<ReturnType>
<tt:value ref="ROOT.RETURNTYPE"/>
</ReturnType>
<ProcessedParts>
<tt:value ref="ROOT.PROCESSEDPARTS"/>
</ProcessedParts>
<ScrapParts>
<tt:value ref="ROOT.SCRAPPARTS"/>
</ScrapParts>
<MissingParts>
<tt:value ref="ROOT.MISSINGPARTS"/>
</MissingParts>
<TargetProcessingTimePerPiece>
<tt:value ref="ROOT.TARGETPROCESSINGTIMEPERPIECE"/>
</TargetProcessingTimePerPiece>
<ProcessingTime>
<tt:value ref="ROOT.PROCESSINGTIME"/>
</ProcessingTime>
<SetupTime>
<tt:value ref="ROOT.SETUPTIME"/>
</SetupTime>
<MeasuringTime>
<tt:value ref="ROOT.MEASURINGTIME"/>
</MeasuringTime>
<OperationStart>
<tt:value ref="ROOT.OPERATIONSTART"/>
</OperationStart>
<OperationEnd>
<tt:value ref="ROOT.OPERATIONEND"/>
</OperationEnd>
<PartWeight>
<tt:value ref="ROOT.PARTWEIGHT"/>
</PartWeight>
<PartArea>
<tt:value ref="ROOT.PARTAREA"/>
</PartArea>
<PartLength>
<tt:value ref="ROOT.PARTLENGTH"/>
</PartLength>
<PartWidth>
<tt:value ref="ROOT.PARTWIDTH"/>
</PartWidth>
<Assembly>
<tt:value ref="ROOT.ASSEMBLY"/>
</Assembly>
<DataExt>
<tt:value ref="ROOT.DATAEXT"/>
</DataExt>
<OrderNoExt>
<tt:value ref="ROOT.ORDERNOEXT"/>
</OrderNoExt>
<CollectiveOrder>
<tt:value ref="ROOT.COLLECTIVEORDER"/>
</CollectiveOrder>
<ErpID>
<tt:value ref="ROOT.ERPID"/>
</ErpID>
<QuantityReports tt:ref="ROOT.QUANTITYREPORTS">
<QuantityReport>
<ReportingTime>
<tt:value ref="QUANTITYREPORT.REPORTINGTIME"/>
</ReportingTime>
<ProcessedParts>
<tt:value ref="QUANTITYREPORT.PROCESSEDPARTS"/>
</ProcessedParts>
<ScrapParts>
<tt:value ref="QUANTITYREPORT.SCRAPPARTS"/>
</ScrapParts>
<MissingParts>
<tt:value ref="QUANTITYREPORT.MISSINGPARTS"/>
</MissingParts>
<BatchNo>
<tt:value ref="QUANTITYREPORT.BATCHNO"/>
</BatchNo>
<WorkPlace>
<tt:value ref="QUANTITYREPORT.WORKPLACE"/>
</WorkPlace>
<ReportedBy>
<tt:value ref="QUANTITYREPORT.REPORTEDBY"/>
</ReportedBy>
<Terminal>
<tt:value ref="QUANTITYREPORT.TERMINAL"/>
</Terminal>
</QuantityReport>
</QuantityReports>
<Consumption tt:ref="ROOT.CONSUMPTION">
<tt:loop name="item" ref="RESOURCECONSUMPTION">
<ResourceConsumption>
<ResourceDescription>
<tt:value ref="$item.RESOURCEDESCRIPTION"/>
</ResourceDescription>
<ResourceNote>
<tt:value ref="$item.RESOURCENOTE"/>
</ResourceNote>
<ResourceCategory>
<tt:value ref="$item.RESOURCECATEGORY"/>
</ResourceCategory>
<Consumption>
<tt:value ref="$item.CONSUMPTION"/>
</Consumption>
<UnitOfConsumption>
<tt:value ref="$item.UNITOFCONSUMPTION"/>
</UnitOfConsumption>
<Rawmaterial>
<tt:value ref="$item.RAWMATERIAL"/>
</Rawmaterial>
<Dimensions>
<Length>
<tt:value ref="$item.DIMENSIONS.LENGTH"/>
</Length>
<Width>
<tt:value ref="$item.DIMENSIONS.WIDTH"/>
</Width>
<Thickness>
<tt:value ref="$item.DIMENSIONS.THICKNESS"/>
</Thickness>
<Unit>
<tt:value ref="$item.DIMENSIONS.UNIT"/>
</Unit>
</Dimensions>
</ResourceConsumption>
</tt:loop>
</Consumption>
</Operation>
</ProductionOperationFeedback>
</PPSExport>
</tt:template>
</tt:transform>
转化的输入结构(部分截图)如下:
STRAN的调用方式如下:
data: lo_cx_st_match_element type ref to cx_st_match_element,
lv_message type string.
data: ls_input type ty_order.
TRY.
CALL TRANSFORMATION zxxx
SOURCE XML lv_xml
RESULT root = ls_input.
CATCH cx_st_match_element INTO lo_cx_st_match_element.
lv_message = lo_cx_st_match_element->get_text( ).
ev_type = 'E'.
ev_mess = '传入XML文件解析有误'.
ENDTRY.
方法二:调用SAP方法按照node来解析xml
if lv_xml is not initial.
try.
* CALL TRANSFORMATION zmes004_input
* SOURCE XML lv_xml
* RESULT root = ls_input.
l_ixml = cl_ixml=>create( ).
l_streamfactory = l_ixml->create_stream_factory( ).
l_istream = l_streamfactory->create_istream_string(
string = lv_xml ).
l_document = l_ixml->create_document( ).
l_parser = l_ixml->create_parser(
stream_factory = l_streamfactory
istream = l_istream
document = l_document ).
if l_parser->parse( ) ne 0.
if l_parser->num_errors( ) ne 0.
l_parse_error = l_parser->get_error( index = l_index ).
ev_type = 'E'.
ev_mess = 'xml解析有误'.
endif.
endif.
if l_parser->is_dom_generating( ) eq 'X'.
perform frm_process_dom_bg using l_document
changing ls_input.
endif.
catch cx_st_match_element into lo_cx_st_match_element.
lv_message = lo_cx_st_match_element->get_text( ).
ev_type = 'E'.
ev_mess = '传入XML文件解析有误'.
endtry.
form frm_process_dom_bg using l_document type ref to if_ixml_document
changing ps_stru type ty_order.
data: lo_node type ref to if_ixml_node,
lo_iterator type ref to if_ixml_node_iterator.
data: lo_nodemap type ref to if_ixml_named_node_map.
data: lo_nodelist2 type ref to if_ixml_node_list,
lo_nodelist3 type ref to if_ixml_node_list,
lo_node2 type ref to if_ixml_node,
lo_node3 type ref to if_ixml_node.
data: lv_name_node type string.
data: lv_name type char30,
lv_value type string.
data: lv_count type i,
lv_index type sy-index,
lv_prefix type string.
data lo_attr type ref to if_ixml_node.
field-symbols: <fs_field>,
<fs_field1>,
<fs_field2>.
data: ls_quantityreport type ty_report.
data: ls_resourceconsumption type ty_resourceconsumption,
lt_resourceconsumption type table of ty_resourceconsumption.
data: ls_dimensions type ty_dimensions.
lo_node ?= l_document.
check not lo_node is initial.
lo_iterator = lo_node->create_iterator( ).
lo_node = lo_iterator->get_next( ).
data lv_type type i.
while not lo_node is initial.
lv_type = lo_node->get_type( ).
case lv_type.
when if_ixml_node=>co_node_element.
lv_name_node = lo_node->get_name( ).
lv_name = lv_name_node.
translate lv_name to upper case.
if lv_name = 'OPERATION'.
lo_nodemap = lo_node->get_attributes( ).
if not lo_nodemap is initial.
lv_count = lo_nodemap->get_length( ).
do lv_count times.
lv_index = sy-index - 1.
lo_attr = lo_nodemap->get_item( lv_index ).
lv_name_node = lo_attr->get_name( ).
lv_name = lv_name_node.
translate lv_name to upper case.
assign component lv_name of structure ps_stru to <fs_field>.
lv_prefix = lo_attr->get_namespace_prefix( ).
lv_value = lo_attr->get_value( ).
if <fs_field> is assigned.
if lv_value is not initial.
<fs_field> = lv_value.
endif.
endif.
if lv_name = 'ORDERNO'.
exit.
endif.
enddo.
endif.
elseif lv_name = 'REPORTINGTIME' or lv_name = 'PROCESSEDPARTS' or
lv_name = 'SCRAPPARTS' or lv_name = 'MISSINGPARTS' or
lv_name = 'BATCHNO' or lv_name = 'WORKPLACE' or
lv_name = 'REPORTEDBY' or lv_name = 'TERMINAL'.
assign component lv_name of structure ls_quantityreport to <fs_field>.
elseif lv_name = 'RESOURCEDESCRIPTION' or lv_name = 'RESOURCENOTE' or
lv_name = 'RESOURCECATEGORY' or lv_name = 'CONSUMPTION' or
lv_name = 'UNITOFCONSUMPTION' or lv_name = 'RAWMATERIAL' .
assign component lv_name of structure ls_resourceconsumption to <fs_field>.
elseif lv_name = 'LENGTH' or lv_name = 'WIDTH' or
lv_name = 'THICKNESS' or lv_name = 'UNIT'.
assign component lv_name of structure ls_dimensions to <fs_field>.
else.
assign component lv_name of structure ps_stru to <fs_field>.
endif.
when if_ixml_node=>co_node_text or
if_ixml_node=>co_node_cdata_section.
lv_value = lo_node->get_value( ).
if <fs_field> is assigned.
<fs_field> = lv_value.
endif.
if lv_name = 'UNIT'..
ls_resourceconsumption-dimensions = ls_dimensions.
append ls_resourceconsumption to lt_resourceconsumption.
clear ls_resourceconsumption.
clear ls_dimensions.
endif.
endcase.
clear:lo_node,lo_nodemap,lo_attr,lv_name_node.
clear:lv_prefix,lv_value,lv_count,lv_index.
lo_node = lo_iterator->get_next( ).
endwhile.
clear:lo_node,lo_iterator.
ps_stru-quantityreports-quantityreport = ls_quantityreport.
ps_stru-consumption-resourceconsumption = lt_resourceconsumption.
unassign <fs_field>.
endform. "process_dom