如何正确地将数据从两个 SAS 数据集导出到一个 XML 数据文件?
How to properly export data from two SAS datasets to one XML data file?
将多个(两个或更多)SAS 数据集(数据集 1、数据集 2)导出到一个 XML 数据文件并同时引用不同的 table 的正确方法是什么在 XML地图中 ?
执行以下命令时效果很好:
filename xmlout 'path\to\file\want.xml';
libname xmlout xmlv2 xmltype=xmlmap xmlmap='path\to\file\XMLmap.map';
data xmlout.dim;
set work.have_dim;
run;
我从另一个 SAS table 获取数据以导出到 header(ID 和时间如 .map 中所示)。
然后我会修改 .map 为:
<OUTPUT>
<TABLEREF name="dim" />
<TABLEREF name="header" />
</OUTPUT>
并执行以下代码:
data xmlout.header;
set work.have_header;
run;
但是,我无法将 TABLEREF
添加到 header table,因为它在文档中指定:TABLEREF= specifies the name of the table in the XMLMap to be exported. The name must be unique in the XMLMap definition, and the name must be a valid SAS name, which can be up to 32 characters.
(参见 XML LIBNAME 引擎
)
所以我的问题是,如果我不能使用不同的 TABLEREF
,如何将这两个 SAS table 导出到同一个 XML 文件中?
在某些时候,我想使用一个数据步骤,我只需将两个 table 设置在一起,并且只在 .map 中使用一个 TABLEREF
,如下所示:
data aggregated;
set have_dim have_header;
run;
但是,我怎样才能将一些变量重定向到 header
table(ID 和时间)以及 dim
table 中的其他变量XML输出?
所需的 XML output
将是:
<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message" xmlns:ns3="http://www.someurl/common/vo/cube">
<ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:20:47</ns2:time> <!-- the time of the day -->
</ns2:header>
<ns2:content>
<ns2:dataSegment id="OBSERVATION">
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC123" />
<ns3:dim name="VAR" value="VAR1"/>
<ns3:dim name="VALUE" value="Y"/>
<ns3:dim name="DATE" value="2021-01-01T00:00:00" />
</ns3:obs>
</ns2:cube>
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="DEF456" />
<ns3:dim name="VAR" value="VAR2"/>
<ns3:dim name="VALUE" value="N"/>
<ns3:dim name="DATE" value="2021-01-01T00:00:00" />
</ns3:obs>
</ns2:cube>
</ns2:dataSegment>
</ns2:content>
</ns2:message>
为了举例,我只显示了 2 个观察结果。尽管如此,可能会有超过 100 万次观察。
编辑:可重现示例:
SAS Code
:
data have_header;
ID = 1234;
time = datetime();
run;
data have_dim;
infile datalines delimiter=",";
input CODE :. VAR :. VALUE . DATE:datetime20.;
format DATE datetime20.;
datalines;
ABC1,VAR1,Y,31DEC2020:00:00:00
ABC2,VAR2,N,31DEC2020:00:00:00
;
run;
filename dim'path\to\file\dim.xml';
libname dim xmlv2 xmltype=xmlmap xmlmap='path\to\file\map_dim.map';
data dim.dim;
set have_dim;
run;
filename header 'path\to\file\header.xml';
libname header xmlv2 xmltype=xmlmap xmlmap='path\to\file\map_header.map';
data header.header;
set have_header;
run;
libname dim clear;
libname header clear;
*** COMBINE ALL XML FILES;
proc xsl
in = "path\to\file\header.xml"
xsl = "path\to\file\script.xsl"
out = "path\to\file\final_output.xml";
run;
XML.map
暗淡:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ############################################################ -->
<!-- 2021-01-19T08:41:21 -->
<!-- SAS XML Libname Engine Map -->
<!-- Generated by XML Mapper, 904300.0.0.20150204190000_v940m3 -->
<!-- ############################################################ -->
<!-- ### Validation report ### -->
<!-- ############################################################ -->
<!-- XMLMap validation completed successfully. -->
<!-- ############################################################ -->
<SXLEMAP name="AUTO_GEN" version="2.1">
<NAMESPACES count="2">
<NS id="1" prefix="ns2">http://www.someurl/common/vo/message</NS>
<NS id="2" prefix="ns3">http://www.someurl/common/vo/cube</NS>
</NAMESPACES>
<OUTPUT>
<TABLEREF name="dim" />
</OUTPUT>
<!-- ############################################################ -->
<TABLE description="message" name="message">
<TABLE-PATH syntax="XPathENR">/{1}message</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="header" name="header">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}header</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="header_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}header</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="content" name="content">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="content_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="dataSegment" name="dataSegment">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</TABLE-PATH>
<COLUMN class="ORDINAL" name="content_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="dataSegment_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="dataSegment_id">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/@id</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>11</LENGTH>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="cube" name="cube">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</TABLE-PATH>
<COLUMN class="ORDINAL" name="dataSegment_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="cube_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="cube_id">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/@id</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>27</LENGTH>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="obs" name="obs">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</TABLE-PATH>
<COLUMN class="ORDINAL" name="cube_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="obs_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="dim" name="dim">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim</TABLE-PATH>
<COLUMN class="ORDINAL" name="obs_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="dim_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="CODE">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim/CODE</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>8</LENGTH>
</COLUMN>
<COLUMN name="VAR">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim/VAR1</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>8</LENGTH>
</COLUMN>
<COLUMN name="VALUE">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim/VALUE</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>1</LENGTH>
</COLUMN>
<COLUMN name="DATE">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim/DATE</PATH>
<TYPE>numeric</TYPE>
<DATATYPE>datetime</DATATYPE>
<FORMAT width="10">IS8601DA</FORMAT>
<INFORMAT width="10">IS8601DA</INFORMAT>
</COLUMN>
</TABLE>
</SXLEMAP>
XML.map
对于 header:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ############################################################ -->
<!-- 2021-01-19T08:41:21 -->
<!-- SAS XML Libname Engine Map -->
<!-- Generated by XML Mapper, 904300.0.0.20150204190000_v940m3 -->
<!-- ############################################################ -->
<!-- ### Validation report ### -->
<!-- ############################################################ -->
<!-- XMLMap validation completed successfully. -->
<!-- ############################################################ -->
<SXLEMAP name="AUTO_GEN" version="2.1">
<NAMESPACES count="2">
<NS id="1" prefix="ns2">http://www.someurl/common/vo/message</NS>
<NS id="2" prefix="ns3">http://www.someurl/common/vo/cube</NS>
</NAMESPACES>
<OUTPUT>
<TABLEREF name="header" />
</OUTPUT>
<!-- ############################################################ -->
<TABLE description="message" name="message">
<TABLE-PATH syntax="XPathENR">/{1}message</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="header" name="header">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}header</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="header_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}header</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="ID">
<PATH syntax="XPathENR">/{1}message/{1}header/{1}ID</PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="time">
<PATH syntax="XPathENR">/{1}message/{1}header/{1}time</PATH>
<TYPE>numeric</TYPE>
<DATATYPE>datetime</DATATYPE>
<FORMAT width="19">IS8601DT</FORMAT>
<INFORMAT width="19">IS8601DT</INFORMAT>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="content" name="content">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="content_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="dataSegment" name="dataSegment">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</TABLE-PATH>
<COLUMN class="ORDINAL" name="content_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="dataSegment_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="dataSegment_id">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/@id</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>11</LENGTH>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="cube" name="cube">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</TABLE-PATH>
<COLUMN class="ORDINAL" name="dataSegment_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="cube_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="cube_id">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/@id</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>27</LENGTH>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="obs" name="obs">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</TABLE-PATH>
<COLUMN class="ORDINAL" name="cube_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="obs_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="dim" name="dim">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim</TABLE-PATH>
<COLUMN class="ORDINAL" name="obs_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="dim_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
</SXLEMAP>
XML output for dim
(dim.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!--
SAS XML Libname Engine (SAS92XML)
SAS XMLMap Generated Output
Version 9.04.01M3P06242015
Created 2021-01-19T09:20:47
-->
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message">
<ns2:content>
<ns2:dataSegment>
<ns2:cube>
<ns3:obs xmlns:ns3="http://www.someurl/common/vo/cube">
<ns3:dim>
<CODE>ABC1</CODE>
<VAR1>VAR1</VAR1>
<VALUE>Y</VALUE>
<DATE>2020-12-31T00:00:00</DATE>
</ns3:dim>
<ns3:dim>
<CODE>ABC2</CODE>
<VAR1>VAR2</VAR1>
<VALUE>N</VALUE>
<DATE>2020-12-31T00:00:00</DATE>
</ns3:dim>
</ns3:obs>
</ns2:cube>
</ns2:dataSegment>
</ns2:content>
</ns2:message>
XML output for header
(header.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!--
SAS XML Libname Engine (SAS92XML)
SAS XMLMap Generated Output
Version 9.04.01M3P06242015
Created 2021-01-19T09:39:44
-->
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message">
<ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:39:44</ns2:time>
</ns2:header>
</ns2:message>
期望的最终 XML 输出:
<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message" xmlns:ns3="http://www.someurl/common/vo/cube">
<ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:20:47</ns2:time> <!-- the time of the day -->
</ns2:header>
<ns2:content>
<ns2:dataSegment id="OBSERVATION">
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC1" />
<ns3:dim name="VAR" value="VAR1"/>
<ns3:dim name="VALUE" value="Y"/>
<ns3:dim name="DATE" value="2020-12-31T00:00:00" />
</ns3:obs>
</ns2:cube>
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC2" />
<ns3:dim name="VAR" value="VAR2"/>
<ns3:dim name="VALUE" value="N"/>
<ns3:dim name="DATE" value="2020-12-31T00:00:00" />
</ns3:obs>
</ns2:cube>
</ns2:dataSegment>
</ns2:content>
</ns2:message>
将 proc xls 与 Parfait 一起使用时的结果 script.xls:
<?xml version="1.0" encoding="UTF-8"?><ns2:message xmlns:ns2="http://www.someurl/common/vo/message"><ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:39:44</ns2:time>
</ns2:header></ns2:message>
考虑 XSLT, the special purpose language designed to transform XML files, such as combining from different documents. SAS can run XSLT 1.0 even 2.0 using proc xsl
。
但是,您实际上需要两个 XSLT 转换,因为您想要的输出不完全是两个 XML 文件的堆栈,即 dim.xml
中的元素被迁移到属性。
XSLT 1(另存为.xsl
文件,一个特殊的.xml
文件)
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="http://www.someurl/common/vo/message"
xmlns:ns3="http://www.someurl/common/vo/cube">
<xsl:output indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/ns2:message">
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message" xmlns:ns3="http://www.someurl/common/vo/cube">
<xsl:apply-templates select="ns2:content"/>
</ns2:message>
</xsl:template>
<xsl:template match="ns2:content">
<xsl:copy>
<xsl:apply-templates select="ns2:dataSegment"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns2:dataSegment">
<xsl:copy>
<xsl:attribute name="id">OBSERVATION</xsl:attribute>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns2:cube|ns3:obs">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="ns3:dim">
<ns2:cube id="ID_CODE">
<ns3:obs>
<xsl:for-each select="*">
<ns3:dim>
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="text()"/>
</xsl:attribute>
</ns3:dim>
</xsl:for-each>
</ns3:obs>
</ns2:cube>
</xsl:template>
</xsl:transform>
XSLT 2 (另存为 .xsl 文件;使用带有 file://
关键字的绝对路径引用)
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="http://www.someurl/common/vo/message">
<xsl:output indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/ns2:message">
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message" xmlns:ns3="http://www.someurl/common/vo/cube">
<!-- COPY CURRENT DATA -->
<xsl:copy-of select="*"/>
<!-- COMBINE ALL DATA FROM NEW dim.xml -->
<xsl:copy-of select="document('file://absolute/path/to/new_dim.xml')/ns2:message/*" />
</ns2:message>
</xsl:template>
</xsl:transform>
SAS (使用宏输出多个文件)
*** OUTPUT INDIVIDUAL XML FILES;
%macro output_xmls(dset);
filename xmlout "path\to\file\&dset..xml";
libname xmlout xmlv2 xmltype=xmlmap xmlmap='path\to\file\XMLmap.map';
data xmlout.&dset;
set work.&dset;
run;
libname xmlout clear;
%mend output_xmls;
%output_xmls(header);
%output_xmls(dim);
*** TRANSFORM RAW dim.xml;
proc xsl
in = "path\to\file\dim.xml"
xsl = "path\to\file\script_1.xsl"
out = "path\to\file\new_dim.xml";
run;
*** COMBINE header.xml and new_dim.xml FILES;
proc xsl
in = "path\to\file\header.xml"
xsl = "path\to\file\script_2.xsl"
out = "path\to\file\final.xml";
run;
输出
<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message"
xmlns:ns3="http://www.someurl/common/vo/cube">
<ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:39:44</ns2:time>
</ns2:header>
<ns2:content>
<ns2:dataSegment id="OBSERVATION">
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC1"/>
<ns3:dim name="VAR1" value="VAR1"/>
<ns3:dim name="VALUE" value="Y"/>
<ns3:dim name="DATE" value="2020-12-31T00:00:00"/>
</ns3:obs>
</ns2:cube>
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC2"/>
<ns3:dim name="VAR1" value="VAR2"/>
<ns3:dim name="VALUE" value="N"/>
<ns3:dim name="DATE" value="2020-12-31T00:00:00"/>
</ns3:obs>
</ns2:cube>
</ns2:dataSegment>
</ns2:content>
</ns2:message>
将多个(两个或更多)SAS 数据集(数据集 1、数据集 2)导出到一个 XML 数据文件并同时引用不同的 table 的正确方法是什么在 XML地图中 ?
执行以下命令时效果很好:
filename xmlout 'path\to\file\want.xml';
libname xmlout xmlv2 xmltype=xmlmap xmlmap='path\to\file\XMLmap.map';
data xmlout.dim;
set work.have_dim;
run;
我从另一个 SAS table 获取数据以导出到 header(ID 和时间如 .map 中所示)。 然后我会修改 .map 为:
<OUTPUT>
<TABLEREF name="dim" />
<TABLEREF name="header" />
</OUTPUT>
并执行以下代码:
data xmlout.header;
set work.have_header;
run;
但是,我无法将 TABLEREF
添加到 header table,因为它在文档中指定:TABLEREF= specifies the name of the table in the XMLMap to be exported. The name must be unique in the XMLMap definition, and the name must be a valid SAS name, which can be up to 32 characters.
(参见 XML LIBNAME 引擎
)
所以我的问题是,如果我不能使用不同的 TABLEREF
,如何将这两个 SAS table 导出到同一个 XML 文件中?
在某些时候,我想使用一个数据步骤,我只需将两个 table 设置在一起,并且只在 .map 中使用一个 TABLEREF
,如下所示:
data aggregated;
set have_dim have_header;
run;
但是,我怎样才能将一些变量重定向到 header
table(ID 和时间)以及 dim
table 中的其他变量XML输出?
所需的 XML output
将是:
<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message" xmlns:ns3="http://www.someurl/common/vo/cube">
<ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:20:47</ns2:time> <!-- the time of the day -->
</ns2:header>
<ns2:content>
<ns2:dataSegment id="OBSERVATION">
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC123" />
<ns3:dim name="VAR" value="VAR1"/>
<ns3:dim name="VALUE" value="Y"/>
<ns3:dim name="DATE" value="2021-01-01T00:00:00" />
</ns3:obs>
</ns2:cube>
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="DEF456" />
<ns3:dim name="VAR" value="VAR2"/>
<ns3:dim name="VALUE" value="N"/>
<ns3:dim name="DATE" value="2021-01-01T00:00:00" />
</ns3:obs>
</ns2:cube>
</ns2:dataSegment>
</ns2:content>
</ns2:message>
为了举例,我只显示了 2 个观察结果。尽管如此,可能会有超过 100 万次观察。
编辑:可重现示例:
SAS Code
:
data have_header;
ID = 1234;
time = datetime();
run;
data have_dim;
infile datalines delimiter=",";
input CODE :. VAR :. VALUE . DATE:datetime20.;
format DATE datetime20.;
datalines;
ABC1,VAR1,Y,31DEC2020:00:00:00
ABC2,VAR2,N,31DEC2020:00:00:00
;
run;
filename dim'path\to\file\dim.xml';
libname dim xmlv2 xmltype=xmlmap xmlmap='path\to\file\map_dim.map';
data dim.dim;
set have_dim;
run;
filename header 'path\to\file\header.xml';
libname header xmlv2 xmltype=xmlmap xmlmap='path\to\file\map_header.map';
data header.header;
set have_header;
run;
libname dim clear;
libname header clear;
*** COMBINE ALL XML FILES;
proc xsl
in = "path\to\file\header.xml"
xsl = "path\to\file\script.xsl"
out = "path\to\file\final_output.xml";
run;
XML.map
暗淡:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ############################################################ -->
<!-- 2021-01-19T08:41:21 -->
<!-- SAS XML Libname Engine Map -->
<!-- Generated by XML Mapper, 904300.0.0.20150204190000_v940m3 -->
<!-- ############################################################ -->
<!-- ### Validation report ### -->
<!-- ############################################################ -->
<!-- XMLMap validation completed successfully. -->
<!-- ############################################################ -->
<SXLEMAP name="AUTO_GEN" version="2.1">
<NAMESPACES count="2">
<NS id="1" prefix="ns2">http://www.someurl/common/vo/message</NS>
<NS id="2" prefix="ns3">http://www.someurl/common/vo/cube</NS>
</NAMESPACES>
<OUTPUT>
<TABLEREF name="dim" />
</OUTPUT>
<!-- ############################################################ -->
<TABLE description="message" name="message">
<TABLE-PATH syntax="XPathENR">/{1}message</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="header" name="header">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}header</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="header_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}header</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="content" name="content">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="content_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="dataSegment" name="dataSegment">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</TABLE-PATH>
<COLUMN class="ORDINAL" name="content_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="dataSegment_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="dataSegment_id">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/@id</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>11</LENGTH>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="cube" name="cube">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</TABLE-PATH>
<COLUMN class="ORDINAL" name="dataSegment_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="cube_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="cube_id">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/@id</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>27</LENGTH>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="obs" name="obs">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</TABLE-PATH>
<COLUMN class="ORDINAL" name="cube_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="obs_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="dim" name="dim">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim</TABLE-PATH>
<COLUMN class="ORDINAL" name="obs_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="dim_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="CODE">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim/CODE</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>8</LENGTH>
</COLUMN>
<COLUMN name="VAR">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim/VAR1</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>8</LENGTH>
</COLUMN>
<COLUMN name="VALUE">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim/VALUE</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>1</LENGTH>
</COLUMN>
<COLUMN name="DATE">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim/DATE</PATH>
<TYPE>numeric</TYPE>
<DATATYPE>datetime</DATATYPE>
<FORMAT width="10">IS8601DA</FORMAT>
<INFORMAT width="10">IS8601DA</INFORMAT>
</COLUMN>
</TABLE>
</SXLEMAP>
XML.map
对于 header:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ############################################################ -->
<!-- 2021-01-19T08:41:21 -->
<!-- SAS XML Libname Engine Map -->
<!-- Generated by XML Mapper, 904300.0.0.20150204190000_v940m3 -->
<!-- ############################################################ -->
<!-- ### Validation report ### -->
<!-- ############################################################ -->
<!-- XMLMap validation completed successfully. -->
<!-- ############################################################ -->
<SXLEMAP name="AUTO_GEN" version="2.1">
<NAMESPACES count="2">
<NS id="1" prefix="ns2">http://www.someurl/common/vo/message</NS>
<NS id="2" prefix="ns3">http://www.someurl/common/vo/cube</NS>
</NAMESPACES>
<OUTPUT>
<TABLEREF name="header" />
</OUTPUT>
<!-- ############################################################ -->
<TABLE description="message" name="message">
<TABLE-PATH syntax="XPathENR">/{1}message</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="header" name="header">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}header</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="header_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}header</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="ID">
<PATH syntax="XPathENR">/{1}message/{1}header/{1}ID</PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="time">
<PATH syntax="XPathENR">/{1}message/{1}header/{1}time</PATH>
<TYPE>numeric</TYPE>
<DATATYPE>datetime</DATATYPE>
<FORMAT width="19">IS8601DT</FORMAT>
<INFORMAT width="19">IS8601DT</INFORMAT>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="content" name="content">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content</TABLE-PATH>
<COLUMN class="ORDINAL" name="message_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="content_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="dataSegment" name="dataSegment">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</TABLE-PATH>
<COLUMN class="ORDINAL" name="content_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="dataSegment_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="dataSegment_id">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/@id</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>11</LENGTH>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="cube" name="cube">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</TABLE-PATH>
<COLUMN class="ORDINAL" name="dataSegment_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="cube_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN name="cube_id">
<PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/@id</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>27</LENGTH>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="obs" name="obs">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</TABLE-PATH>
<COLUMN class="ORDINAL" name="cube_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="obs_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
<!-- ############################################################ -->
<TABLE description="dim" name="dim">
<TABLE-PATH syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim</TABLE-PATH>
<COLUMN class="ORDINAL" name="obs_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
<COLUMN class="ORDINAL" name="dim_ORDINAL">
<INCREMENT-PATH beginend="BEGIN" syntax="XPathENR">/{1}message/{1}content/{1}dataSegment/{1}cube/{2}obs/{2}dim</INCREMENT-PATH>
<TYPE>numeric</TYPE>
<DATATYPE>integer</DATATYPE>
</COLUMN>
</TABLE>
</SXLEMAP>
XML output for dim
(dim.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!--
SAS XML Libname Engine (SAS92XML)
SAS XMLMap Generated Output
Version 9.04.01M3P06242015
Created 2021-01-19T09:20:47
-->
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message">
<ns2:content>
<ns2:dataSegment>
<ns2:cube>
<ns3:obs xmlns:ns3="http://www.someurl/common/vo/cube">
<ns3:dim>
<CODE>ABC1</CODE>
<VAR1>VAR1</VAR1>
<VALUE>Y</VALUE>
<DATE>2020-12-31T00:00:00</DATE>
</ns3:dim>
<ns3:dim>
<CODE>ABC2</CODE>
<VAR1>VAR2</VAR1>
<VALUE>N</VALUE>
<DATE>2020-12-31T00:00:00</DATE>
</ns3:dim>
</ns3:obs>
</ns2:cube>
</ns2:dataSegment>
</ns2:content>
</ns2:message>
XML output for header
(header.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!--
SAS XML Libname Engine (SAS92XML)
SAS XMLMap Generated Output
Version 9.04.01M3P06242015
Created 2021-01-19T09:39:44
-->
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message">
<ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:39:44</ns2:time>
</ns2:header>
</ns2:message>
期望的最终 XML 输出:
<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message" xmlns:ns3="http://www.someurl/common/vo/cube">
<ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:20:47</ns2:time> <!-- the time of the day -->
</ns2:header>
<ns2:content>
<ns2:dataSegment id="OBSERVATION">
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC1" />
<ns3:dim name="VAR" value="VAR1"/>
<ns3:dim name="VALUE" value="Y"/>
<ns3:dim name="DATE" value="2020-12-31T00:00:00" />
</ns3:obs>
</ns2:cube>
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC2" />
<ns3:dim name="VAR" value="VAR2"/>
<ns3:dim name="VALUE" value="N"/>
<ns3:dim name="DATE" value="2020-12-31T00:00:00" />
</ns3:obs>
</ns2:cube>
</ns2:dataSegment>
</ns2:content>
</ns2:message>
将 proc xls 与 Parfait 一起使用时的结果 script.xls:
<?xml version="1.0" encoding="UTF-8"?><ns2:message xmlns:ns2="http://www.someurl/common/vo/message"><ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:39:44</ns2:time>
</ns2:header></ns2:message>
考虑 XSLT, the special purpose language designed to transform XML files, such as combining from different documents. SAS can run XSLT 1.0 even 2.0 using proc xsl
。
但是,您实际上需要两个 XSLT 转换,因为您想要的输出不完全是两个 XML 文件的堆栈,即 dim.xml
中的元素被迁移到属性。
XSLT 1(另存为.xsl
文件,一个特殊的.xml
文件)
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="http://www.someurl/common/vo/message"
xmlns:ns3="http://www.someurl/common/vo/cube">
<xsl:output indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/ns2:message">
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message" xmlns:ns3="http://www.someurl/common/vo/cube">
<xsl:apply-templates select="ns2:content"/>
</ns2:message>
</xsl:template>
<xsl:template match="ns2:content">
<xsl:copy>
<xsl:apply-templates select="ns2:dataSegment"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns2:dataSegment">
<xsl:copy>
<xsl:attribute name="id">OBSERVATION</xsl:attribute>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns2:cube|ns3:obs">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="ns3:dim">
<ns2:cube id="ID_CODE">
<ns3:obs>
<xsl:for-each select="*">
<ns3:dim>
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="text()"/>
</xsl:attribute>
</ns3:dim>
</xsl:for-each>
</ns3:obs>
</ns2:cube>
</xsl:template>
</xsl:transform>
XSLT 2 (另存为 .xsl 文件;使用带有 file://
关键字的绝对路径引用)
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="http://www.someurl/common/vo/message">
<xsl:output indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/ns2:message">
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message" xmlns:ns3="http://www.someurl/common/vo/cube">
<!-- COPY CURRENT DATA -->
<xsl:copy-of select="*"/>
<!-- COMBINE ALL DATA FROM NEW dim.xml -->
<xsl:copy-of select="document('file://absolute/path/to/new_dim.xml')/ns2:message/*" />
</ns2:message>
</xsl:template>
</xsl:transform>
SAS (使用宏输出多个文件)
*** OUTPUT INDIVIDUAL XML FILES;
%macro output_xmls(dset);
filename xmlout "path\to\file\&dset..xml";
libname xmlout xmlv2 xmltype=xmlmap xmlmap='path\to\file\XMLmap.map';
data xmlout.&dset;
set work.&dset;
run;
libname xmlout clear;
%mend output_xmls;
%output_xmls(header);
%output_xmls(dim);
*** TRANSFORM RAW dim.xml;
proc xsl
in = "path\to\file\dim.xml"
xsl = "path\to\file\script_1.xsl"
out = "path\to\file\new_dim.xml";
run;
*** COMBINE header.xml and new_dim.xml FILES;
proc xsl
in = "path\to\file\header.xml"
xsl = "path\to\file\script_2.xsl"
out = "path\to\file\final.xml";
run;
输出
<?xml version="1.0" encoding="UTF-8"?>
<ns2:message xmlns:ns2="http://www.someurl/common/vo/message"
xmlns:ns3="http://www.someurl/common/vo/cube">
<ns2:header>
<ns2:ID>1234</ns2:ID>
<ns2:time>2021-01-19T09:39:44</ns2:time>
</ns2:header>
<ns2:content>
<ns2:dataSegment id="OBSERVATION">
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC1"/>
<ns3:dim name="VAR1" value="VAR1"/>
<ns3:dim name="VALUE" value="Y"/>
<ns3:dim name="DATE" value="2020-12-31T00:00:00"/>
</ns3:obs>
</ns2:cube>
<ns2:cube id="ID_CODE">
<ns3:obs>
<ns3:dim name="CODE" value="ABC2"/>
<ns3:dim name="VAR1" value="VAR2"/>
<ns3:dim name="VALUE" value="N"/>
<ns3:dim name="DATE" value="2020-12-31T00:00:00"/>
</ns3:obs>
</ns2:cube>
</ns2:dataSegment>
</ns2:content>
</ns2:message>