如何解决如何使用 cl_xslt_processor 解析带有命名空间的 XML 文档?
我有以下XML
<?xml version="1.0" encoding="UTF-8"?>
<!--Version #1.0-->
<NominaIndividual xmlns="dian:gov:co:facturaelectronica:NominaIndividual"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"
xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
SchemaLocation=""
xsi:schemaLocation="dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd">
<Devengados>
<Anticipos>
<Anticipo>1.00</Anticipo>
<Anticipo>2.00</Anticipo>
<Anticipo>3.00</Anticipo>
</Anticipos>
</Devengados>
<Deducciones>
<Anticipos>
<Anticipo>4.00</Anticipo>
<Anticipo>5.00</Anticipo>
<Anticipo>6.00</Anticipo>
</Anticipos>
</Deducciones>
</NominaIndividual>
这个 XML
被压缩成一个 XSTRING
。从这个 XSTRING
我想检索我想要的所有节点,例如 NominaIndividual/Devengados/Anticipos
。
到目前为止,我可以使用下面的代码成功地做到这一点,但是只有如果我从 NominaIndividual
中完全删除所有命名空间:
DATA lo_xslt TYPE REF TO cl_xslt_processor.
DATA lo_nodes TYPE REF TO if_ixml_node_collection.
CREATE OBJECT lo_xslt.
lo_xslt->set_source_xstring( iv_xml ).
lo_xslt->set_expression( '//Devengados/Anticipos/Anticipo').
lo_xslt->run( '' ).
lo_nodes = lo_xslt->get_nodes( ).
ro_iterator = lo_nodes->create_iterator( ).
ro_node = ro_iterator->get_next( ).
在这段代码中,最后一个对象 ro_node
包含我需要的所有信息。但问题是:只有当我从 NominaIndividual
中完全删除所有命名空间时才会创建此对象:
例如,如果我将 XML 修改为此,它会起作用:
<?xml version="1.0" encoding="UTF-8"?>
<!--Version #1.0-->
<NominaIndividual>
...
</NominaIndividual>
但是这个,那是原始的 XML,没有:
<?xml version="1.0" encoding="UTF-8"?>
<!--Version #1.0-->
<NominaIndividual xmlns="dian:gov:co:facturaelectronica:NominaIndividual"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"
xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
SchemaLocation=""
xsi:schemaLocation="dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd">
...
</NominaIndividual>
这就是说,我如何通过 XPATH
维护命名空间来浏览这个 XML 树?我知道方法 cl_xslt_processor->set_expression
有一个关于命名空间的参数,但我不知道如何正确使用 ir。
解决方法
您可以像这样为父元素使用通配符:
DATA(l_xslt) = new cl_xslt_processor( ).
l_xslt->set_source_string(
` <?xml version="1.0" encoding="UTF-8"?> ` &&
` <NominaIndividual xmlns="dian:gov:co:facturaelectronica:NominaIndividual" ` &&
` xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" ` &&
` xmlns:ds="http://www.w3.org/2000/09/xmldsig#" ` &&
...
` </Anticipos> ` &&
` </Deducciones> ` &&
` </NominaIndividual> ` ).
l_xslt->set_expression( expression = '//*[local-name()="Anticipo"]' ).
l_xslt->run( '' ).
DATA(nodes) = l_xslt->get_nodes( ).
DO nodes->get_length( ) TIMES.
DATA(node) = nodes->get_item( sy-index - 1 ).
WRITE node->get_value( ).
ENDDO.
在 set_expression()
方法中指定命名空间时的一般规则是通过空格:
l_xslt->set_expression(
expression = 'sp1:a/sp2:foo'
nsdeclarations = 'sp1 http://uri.com sp2 http://uri2.com sp3 http://uri3.com'
).
最后,不要使用它。它是 deprecated(第 24 页),请改用 XSLT 转换
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。