gpt4 book ai didi

xml - 使用 XMLMAP 从 SAS 写入分层 XML 文件

转载 作者:数据小太阳 更新时间:2023-10-29 02:25:35 29 4
gpt4 key购买 nike

我必须从 SAS 数据集生成一个 XML 文件。 XML文件的格式定义非常严格,我需要准确匹配。我正在使用 SAS 9.4(注意:并坚持使用它!)并利用 XMLMAP 和 libname xmlv2。我觉得我非常接近解决方案,但还有最后一个障碍我似乎无法通过!

XML 文件有一个 3 级结构,一个 2 级元素包含所有 3 级元素。无论我尝试什么,我所有的 3 级元素似乎都生成了它们自己的 2 级元素。似乎 SAS xmlv2 libname 引擎在导入或导出完全相同的数据时甚至工作方式不同!下面重现的示例和步骤 - 如果可以,请帮助我!

示例数据

数据是文件列表和与这些文件相关的一些属性。这些属性对所有文件都是通用的,只有列表中的文件名不同。这将在 SAS 工作中创建一个测试数据集:

proc sql;

create table input_data
(col1 char(1),
col2 char(1),
file char(20));

insert into input_data
values ('1', '2', 'file1.txt')
values ('1', '2', 'file2.txt');

quit;

所需的输出 XML

请注意,所有文件名都列在各自的 FILE 元素中,嵌套在单个 FILES 元素中。公共(public)属性是主 FILE_INFO 元素中的元素。这是我需要能够输出的结构。

<?xml version="1.0" encoding="windows-1252" ?>

<FILE_INFO>
<COL1>1</COL1>
<COL2>2</COL2>
<FILES>
<FILE>file1.txt</FILE>
<FILE>file2.txt</FILE>
</FILES>
</FILE_INFO>

我创建的 SAS XMLMAP

<?xml version="1.0" encoding="windows-1252"?>
<!-- ############################################################ -->
<!-- this is a map file for SAS-XML conversion -->
<!-- ############################################################ -->
<SXLEMAP name="file_test" version="2.1">

<!-- ############################################################ -->
<OUTPUT>
<TABLEREF name="FILE_INFO"/>
</OUTPUT>

<NAMESPACES count="0"/>

<!-- ############################################################ -->
<TABLE name="FILE_INFO">
<TABLE-PATH syntax="XPath">/FILE_INFO/FILES/FILE</TABLE-PATH>

<COLUMN name="col1" retain="YES">
<PATH syntax="XPath">/FILE_INFO/COL1</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>1</LENGTH>
</COLUMN>

<COLUMN name="col2" retain="YES">
<PATH syntax="XPath">/FILE_INFO/COL2</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>1</LENGTH>
</COLUMN>

<COLUMN name="file">
<PATH syntax="XPath">/FILE_INFO/FILES/FILE</PATH>
<TYPE>character</TYPE>
<DATATYPE>string</DATATYPE>
<LENGTH>20</LENGTH>
</COLUMN>

</TABLE>
</SXLEMAP>

使用 XMLMAP 输出 XML 的 SAS 代码

filename out "C:\myfolder\test_out.xml";
libname out xmlv2 xmltype=xmlmap xmlmap="C:\myfolder\file_test.map";

data out.FILE_INFO;
set work.input_data;
run;

实际结果 XML

<?xml version="1.0" encoding="windows-1252" ?>

<FILE_INFO>
<FILES>
<FILE>file1.txt</FILE>
</FILES>
<COL1>1</COL1>
<COL2>2</COL2>
<FILES>
<FILE>file2.txt</FILE>
</FILES>
</FILE_INFO>

重现步骤

使用上面的代码生成测试数据集。将 XMLMAP 保存到 file_test.map 中。运行 SAS 代码,将生成的 XML 与所需结果进行比较。

问题

看看那里发生了什么?所有的 FILE 元素都在它们自己的 FILES 元素中。无论我的数据中有多少行具有单独的文件名,都会发生这种情况:每一行都有自己的 FILES 元素。

有趣的是,如果我获取上面所需的输出 XML 文件,并使用完全相同的 XMLMAP 将其返回 给 SAS,则生成的 SAS 数据集与我的原始输入数据集完全相同!

我试过摆弄 XMLMAP 中的 RETAIN-options,我试过将 FILES 定义为输入数据集中它自己的列并在 XMLMAP 中定义它,我试过各种随机的东西但无济于事.有什么想法吗?

最佳答案

因为您想要的 XML 涉及到一些复杂的分组,请考虑 XSLT ,专门用于转换 XML 文件的语言。 SAS 9.4 使用带有 proc xsl 的 Saxon-EE 9.3 版引擎维护 XSLT 处理器它允许 XSLT 1.0 或 2.0 脚本。

具体来说,将您的数据导出到原始 xml 文件(无映射)并使用 XSLT 1.0 的 Muenchian Grouping或更简单的 XSLT 2.0 的 xsl:for-each-group .我将两者都包括在内,因为为了可移植性,XSLT 1.0 在其他语言库(Java、Python、PHP、R)中被更广泛地用作默认规范,以防您需要在 SAS 之外运行或 future 的读者使用早期版本。

请注意,您会看到 colsconcat() 内的 XSLT 中进行了硬编码和 <COL>指定模板中的节点。对于其他列,请相应地添加到这些部分。 normalize-space()之所以使用,是因为 SAS 在文本值之前/之后填充了空格。

XSLT 1.0 (另存为 .xsl 文件)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="colkeys" match="INPUT_DATA" use="concat(col1, col2)" />

<xsl:template match="/TABLE">
<FILE_INFO>
<xsl:apply-templates select="INPUT_DATA[generate-id() =
generate-id(key('colkeys', concat(col1, col2)))]"/>
</FILE_INFO>
</xsl:template>

<xsl:template match="INPUT_DATA">

<COL1><xsl:value-of select="normalize-space(col1)"/></COL1>
<COL2><xsl:value-of select="normalize-space(col2)"/></COL2>

<FILES>
<xsl:for-each select="key('colkeys', concat(col1, col2))">
<FILE><xsl:value-of select="normalize-space(file)"/></FILE>
</xsl:for-each>
</FILES>
</xsl:template>

</xsl:stylesheet>

XSLT 2.0 (另存为 .xsl 文件)

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="colkeys" match="INPUT_DATA" use="concat(col1, col2)" />

<xsl:template match="/TABLE">
<FILE_INFO>
<xsl:for-each-group select="INPUT_DATA" group-by="concat(col1, col2)">
<COL1><xsl:value-of select="normalize-space(col1)"/></COL1>
<COL2><xsl:value-of select="normalize-space(col2)"/></COL2>

<FILES>
<xsl:for-each select="current-group()">
<FILE><xsl:value-of select="normalize-space(file)"/></FILE>
</xsl:for-each>
</FILES>
</xsl:for-each-group>
</FILE_INFO>

</xsl:template>

</xsl:stylesheet>

SAS

** EXPORT DATASET TO XML FILE;
filename out "C:\Path\Raw_Output.xml";

libname out xml;

data out.input_data;
set Work.input_data;
run;

libname out clear;

proc xsl
in="C:\Path\Raw_Output.xml"
out="C:\Path\Final_Output.xml"
xsl="C:\Path\XSLT_Script.xsl";
run;

输出

<?xml version="1.0" encoding="UTF-8"?>
<FILE_INFO>
<COL1>1</COL1>
<COL2>2</COL2>
<FILES>
<FILE>file1.txt</FILE>
<FILE>file2.txt</FILE>
</FILES>
</FILE_INFO>

关于xml - 使用 XMLMAP 从 SAS 写入分层 XML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47928039/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com