我正在尝试从此XML中获取标签Totales
及其子元素:
<Body>
<Receptor>
<RUTRecep>9655</RUTRecep>
</Receptor>
<Totales>
<MntNeto>63934</MntNeto>
<TasaIVA>19</TasaIVA>
<MntTotal>76081</MntTotal>
</Totales>
</Body>
我的代码仅返回标签的值,而不是标签名称:
故事
639341976081
我想在Totales
中输入名称和值:
MntNeto
63934
TasaIVA
19
MntTotal
76081
这是我的代码:
DATA(lo_ixml) = cl_ixml=>create( ).
DATA(lo_stream_factory) = lo_ixml->create_stream_factory( ).
DATA(lo_doc) = lo_ixml->create_document( ).
IF lo_ixml->create_parser(
document = lo_doc
stream_factory = lo_stream_factory
istream = lo_stream_factory->create_istream_string( string =
`<Body> ` &&
` <Receptor> ` &&
` <RUTRecep>9655</RUTRecep> ` &&
` </Receptor> ` &&
` <Totales> ` &&
` <MntNeto>63934</MntNeto> ` &&
` <TasaIVA>19</TasaIVA> ` &&
` <MntTotal>76081</MntTotal> ` &&
` </Totales> ` &&
`</Body> ` )
)->parse( ) <> 0.
RETURN.
ENDIF.
DATA(lo_node_col) = lo_doc->get_elements_by_tag_name( name = 'Totales' ).
DATA(lo_iterator) = lo_node_col->create_iterator( ).
DATA(lo_node) = lo_iterator->get_next( ).
WHILE NOT lo_node IS INITIAL.
DATA(lf_name) = lo_node->get_name( ).
DATA(lf_value) = lo_node->get_value( ).
"do something for text
WRITE /: lf_name , lf_value.
lo_node = lo_iterator->get_next( ).
ENDWHILE.
答案 0 :(得分:2)
原因是您使用的节点集合与名称为Totales
的所有XML元素相对应,因此您的集合仅包含一个节点,并且迭代器将仅迭代一个节点。方法get_value
在所有深度级别上串联节点及其子节点的所有文本。
相反,不要使用集合,获取名称为Totales
的元素,在此节点上创建一个迭代器,该迭代器将在此节点及其子节点上进行迭代。
此外,节点既可以是元素,也可以是文本(可能还可以是其他类型,例如属性等)。对于<name>value</name>
,有两个节点,一个是元素类型(名称),一个是文本类型(值) 。这对于处理诸如<a>v1<b>v2</b>v3</a>
之类的XML流很有用。因此,要仅处理<name>value</name>
之类的表格,就必须选择仅包含一个子节点的节点,即文本节点。
DATA(lo_elem) = CAST if_ixml_node( lo_doc->find_from_path( path = '/Body/Totales' ) ).
IF lo_elem IS BOUND.
DATA(lo_iterator) = lo_elem->create_iterator( ).
DATA(lo_node) = lo_iterator->get_next( ). " get /Body/Totales node
WHILE NOT lo_node IS INITIAL.
" Only nodes of the form `<name>value</name>`
IF lo_node->get_type( ) = lo_node->co_node_element
AND lo_node->get_children( )->get_length( ) = 1
AND lo_node->get_first_child( )->get_type( ) = lo_node->co_node_text.
DATA(lf_name) = lo_node->get_name( ).
DATA(lf_value) = lo_node->get_value( ).
"do something for text
WRITE /: lf_name , lf_value.
ENDIF.
lo_node = lo_iterator->get_next( ).
ENDWHILE.
ENDIF.
结果:
MntNeto
63934
TasaIVA
19
MntTotal
76081
答案 1 :(得分:1)
您在代码中所做的就是转换。我的提示是:不要为已经使用XSLT解决的问题编写不必要的代码。
这是在SAP中执行此操作的方法。转到事务STRANS
并在此处创建以下XSL转换。让我们将其命名为ZTEST
。
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:strip-space elements="*"/>
<xsl:template match="Totales">
<xsl:for-each select="child::*">
<xsl:value-of select="local-name()" /><xsl:text>
</xsl:text><xsl:value-of select="text()" /><xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="text() | comment()" />
</xsl:transform>
然后只需使用CALL TRANSFORMATION
即可实现所需的功能。
REPORT ZZZ.
START-OF-SELECTION.
DATA g_string TYPE string.
DATA(g_ref_stream_factory) = cl_ixml=>create( )->create_stream_factory( ).
DATA(g_ostream) = g_ref_stream_factory->create_ostream_cstring( g_string ).
DATA(g_istream) =
g_ref_stream_factory->create_istream_string(
string =
`<Body> ` &&
` <Receptor> ` &&
` <RUTRecep>9655</RUTRecep> ` &&
` </Receptor> ` &&
` <Totales> ` &&
` <MntNeto>63934</MntNeto> ` &&
` <TasaIVA>19</TasaIVA> ` &&
` <MntTotal>76081</MntTotal> ` &&
` </Totales> ` &&
`</Body> ` ).
CALL TRANSFORMATION ZTEST
SOURCE XML g_istream
RESULT XML g_ostream.
SPLIT g_string AT cl_abap_char_utilities=>cr_lf INTO TABLE DATA(g_tab_string).
LOOP AT g_tab_string ASSIGNING FIELD-SYMBOL(<string_line>).
WRITE / <string_line>.
ENDLOOP.