首页 > 解决方案 > 使用 SAS 合并两个 XML 文件

问题描述

我有两个 XML 文件 (AB),我想将它们附加到 XML 文件C中。基本上A只是一个“标题”,B是“主要”内容。

A.xml

<?xml version="1.0" encoding="utf-8" ?>
<!--
      SAS XML Libname Engine (SAS92XML)
      SAS XMLMap Generated Output
      Version 9.04.01M3P06242015
      Created 2021-02-18T16:52:07
  -->

<ns2:message xmlns:ns2="message">
<ns2:header xmlns:ns2="message">
<ns2:ID xmlns:ns2="message">11111</ns2:ID>
<ns2:survey xmlns:ns2="message">AABB</ns2:survey>
<ns2:partner xmlns:ns2="message">ABC</ns2:partner>
<ns2:initialDate xmlns:ns2="message">2020-01-01T00:00:00.000+00:00</ns2:initialDate>
<ns2:timeProduction xmlns:ns2="message">2021-02-18T16:41:35</ns2:timeProduction>
<ns2:type xmlns:ns2="message">TYPEOFMESSAGE</ns2:type>
</ns2:header>
</ns2:message>

B.xml

<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="message"
             xmlns:ns3="send">
   <ns2:content>
      <ns2:dataSegment id="OBSERVATION">
         <ns2:cube id="ABCD">
            <ns3:obs>
               <ns3:dim name="ID" value="1"/>
               <ns3:dim name="FROM" value="2021-02-17"/>
               <ns3:dim name="TO" value="2021-02-19"/>
               <ns3:dim name="VALUE" value="A"/>
            </ns3:obs>
         </ns2:cube>
      </ns2:dataSegment>
   </ns2:content>
</ns2:message>

C.xml (want)

<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="message"
             xmlns:ns3="send">
    <ns2:header>
        <ns2:ID>11111</ns2:ID>
        <ns2:survey>AABB</ns2:survey>
        <ns2:partner>ABC</ns2:partner>
        <ns2:initialDate>2020-01-01T00:00:00.000+00:00</ns2:initialDate>
        <ns2:timeProduction>2021-02-18T16:41:35</ns2:timeProduction>
        <ns2:type>TYPEOFMESSAGE</ns2:type>
   </ns2:header>
   <ns2:content>
      <ns2:dataSegment id="OBSERVATION">
         <ns2:cube id="ABCD">
            <ns3:obs>
               <ns3:dim name="ID" value="1"/>
               <ns3:dim name="FROM" value="2021-02-17"/>
               <ns3:dim name="TO" value="2021-02-19"/>
               <ns3:dim name="VALUE" value="A"/>
            </ns3:obs>
         </ns2:cube>
      </ns2:dataSegment>
   </ns2:content>
</ns2:message>

很长一段时间以来,我一直在使用PROC XSLto appendAB使用以下.xsl脚本

script.xsl

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                             xmlns:ns2="message"> 
  <xsl:output indent="yes" encoding="UTF-8"/>
  <xsl:strip-space elements="*"/>
  
  <xsl:template match="/ns2:message">
    <ns2:message xmlns:ns2="message" xmlns:ns3="send"> 
         <!-- COPY CURRENT DATA -->
         <xsl:copy-of select="*"/>

         <!-- COMBINE ALL DATA FROM file.xml -->
         <xsl:copy-of select="document('file:/path/to/file.xml')/ns2:message/*" />
    </ns2:message>
  </xsl:template> 
  
</xsl:transform>

但是,我发现当B太大(~60MB)时,PROC XSL不会创建C(当B不是那么大时它可以完美地完成工作)。

SAS Code

proc xsl 
   in  = 'path/to/file/A.xml'
   xsl = 'path/to/file/script.xsl'
   out = 'path/to/file/final.xml';
run;

日志中没有错误/警告。

SAS Log

MPRINT(GENERATE_XML):           proc xsl 
   in  = 'path/to/file/A.xml'
   xsl = 'path/to/file/script.xsl'
   out = 'path/to/file/final.xml';
MPRINT(GENERATE_XML):   run;

NOTE: PROCEDURE XSL used (Total process time):
      real time           19.61 seconds
      cpu time            0.00 seconds

由于它是一个很小的插入,实际上附加了 8 行,我想知道是否不可能只阅读B.xml一个步骤并在 xml 文件的顶部data _null_插入(例如使用语句)这 8 行?put

标签: xmlxsltsas

解决方案


如果所有 xml 不在一行中,您可以使用一个data _null_;步骤来读取两个文件并将其堆叠在一个包含标记中。

例子:

仅文本处理。不检查任何形式的有效性。LRECL=如果您INFILEFILE文本行长于默认值 (256) ,您将必须在其中指定

filename xml_a temp;
filename xml_b temp;
filename xml_c 'c:\temp\c_wanted.xml';

* create xml a;
data _null_;
  file xml_a;
  input; put _infile_;
  datalines4;
<?xml version="1.0" encoding="utf-8" ?>
<!--
      SAS XML Libname Engine (SAS92XML)
      SAS XMLMap Generated Output
      Version 9.04.01M3P06242015
      Created 2021-02-18T16:52:07
  -->

<ns2:message xmlns:ns2="message">
<ns2:header xmlns:ns2="message">
<ns2:ID xmlns:ns2="message">11111</ns2:ID>
<ns2:survey xmlns:ns2="message">AABB</ns2:survey>
<ns2:partner xmlns:ns2="message">ABC</ns2:partner>
<ns2:initialDate xmlns:ns2="message">2020-01-01T00:00:00.000+00:00</ns2:initialDate>
<ns2:timeProduction xmlns:ns2="message">2021-02-18T16:41:35</ns2:timeProduction>
<ns2:type xmlns:ns2="message">TYPEOFMESSAGE</ns2:type>
</ns2:header>
</ns2:message>
;;;;

* create xml b;
data _null_;
  file xml_b;
  input; put _infile_;
  datalines4;
<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="message"
             xmlns:ns3="send">
   <ns2:content>
      <ns2:dataSegment id="OBSERVATION">
         <ns2:cube id="ABCD">
            <ns3:obs>
               <ns3:dim name="ID" value="1"/>
               <ns3:dim name="FROM" value="2021-02-17"/>
               <ns3:dim name="TO" value="2021-02-19"/>
               <ns3:dim name="VALUE" value="A"/>
            </ns3:obs>
         </ns2:cube>
      </ns2:dataSegment>
   </ns2:content>
</ns2:message>
;;;;


* stack a and b within message send;

data _null_;
  file xml_c;
  put 
    '<?xml version="1.0" encoding="UTF-8"?>'
  / '<ns2:message xmlns:ns2="message"'
  / '             xmlns:ns3="send">'
  ;

  put /'<!-- file a -->'/;

  flag = 0;
  do while (not eof_a);
    infile xml_a end=eof_a;
    input;

    if not flag and strip(_infile_)=:'<ns2:header xmlns:ns2="message">' then flag=1;

    if flag then put _infile_;

    if flag and strip(_infile_)=:'</ns2:header>' then flag = 0;
  end;

  put /'<!-- file b -->'/;

  flag = 0;
  do while (not eof_b);
    infile xml_b end=eof_b;
    input; 

    if not flag and strip(_infile_)=:'<ns2:content>' then flag=1;

    if flag then put _infile_;

    if flag and strip(_infile_)=:'</ns2:content>' then flag = 0;
  end;

  put 
    '</ns2:message>'
  ;

  stop;
run;

推荐阅读