首页 > 解决方案 > SAS 和 XML:XML 元素名称对于 SAS 变量名称来说太长

问题描述

我尝试使用该代码:

libname phuse xml 'T:\XX\XX\XX\XX\XX\file_name.xml' xmlmeta=schemadata;
data work.study_abc; 
    set phuse.study_abc;    
run;

但是源文件的变量名太长并且发生了 SAS:

ERROR: The XML element name <SomeFieldInXMLfileWhereIsTooLong> is too long for a SAS variable name.
ERROR: Encountered during XMLMap parsing at or near line 891, column 53.

是否存在在“set”中导入 XML 文件期间可以重命名字段的方法?

谢谢你的帮助!

标签: xmlsas

解决方案


考虑使用XSLT,这是一种专门用于转换 XML 文档(例如重命名节点)的语言。您可以使用 SAS 调用 XSLT 1.0 和 2.0 脚本proc xsl,然后导入转换后的 XML 文件。具体来说,使用带有单独模板的身份转换来重命名位于文档中任何位置的任何节点的顶级节点。

XSLT (另存为 .xsl 文件,特殊的 .xml 文件)

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

  <!-- IDENTITY TRANSFORM -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- ADJUST match VALUE AND <shortername> NODES -->
  <xsl:template match="SomeFieldInXMLfileWhereIsTooLong">
    <shortername>
      <xsl:apply-templates select="@*|node()"/>
    </shortername>
  </xsl:template>

</xsl:stylesheet>

SAS

proc xsl 
    in="C:\Path\To\Input.xml"
    out="C:\Path\To\Output.xml"
    xsl="C:\Path\To\XSLT_Script.xsl";
run;

libname phuse xml 'C:\Path\To\Output.xml' xmlmeta=schemadata;

data work.study_abc; 
    set phuse.study_abc;    
run;

为了演示,下面的 XML 包括当前排名前五的 StackOverflow SAS 用户,这些用户具有很长的嵌套节点名称,这些节点名称使用 XSLT 进行转换,并将其输出导入 SAS。

<?xml version="1.0"?>
<stackoverflow>
    <topsasonstackoverflowusersoverallyear2019>
      <user>Joe</user>
      <link>https://stackoverflow.com/users/1623007/joe</link>
      <year_rep>1,005</year_rep>
      <total_rep>56,363</total_rep>
      <tag1>sas</tag1>
      <tag2>sas-macro</tag2>
      <tag3>sql</tag3>
    </topsasonstackoverflowusersoverallyear2019>
    <topsasonstackoverflowusersoverallyear2019>
      <user>Tom</user>
      <link>https://stackoverflow.com/users/4965549/tom</link>
      <year_rep>6,378</year_rep>
      <total_rep>28,990</total_rep>
      <tag1>sas</tag1>
      <tag2>sas-macro</tag2>
      <tag3>sql</tag3>
    </topsasonstackoverflowusersoverallyear2019>
    <topsasonstackoverflowusersoverallyear2019>
      <user>Reeza</user>
      <link>https://stackoverflow.com/users/1919583/reeza</link>
      <year_rep>1,507</year_rep>
      <total_rep>14,671</total_rep>
      <tag1>sas</tag1>
      <tag2>sas-macro</tag2>
      <tag3>sql</tag3>
    </topsasonstackoverflowusersoverallyear2019>
    <topsasonstackoverflowusersoverallyear2019>
      <user>DomPazz</user>
      <link>https://stackoverflow.com/users/2734437/dompazz</link>
      <year_rep>85</year_rep>
      <total_rep>12,001</total_rep>
      <tag1>sas</tag1>
      <tag2>sas-macro</tag2>
      <tag3>sql</tag3>
    </topsasonstackoverflowusersoverallyear2019>
    <topsasonstackoverflowusersoverallyear2019>
      <user>Richard</user>
      <link>https://stackoverflow.com/users/1249962/richard</link>
      <year_rep>5,075</year_rep>
      <total_rep>13,519</total_rep>
      <tag1>sas</tag1>
      <tag2>sas-macro</tag2>
      <tag3>proc-sql</tag3>
    </topsasonstackoverflowusersoverallyear2019>    
</stackoverflow>

XSLT

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

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="topsasonstackoverflowusersoverallyear2019">
    <top_sas_users>
      <xsl:apply-templates select="@*|node()"/>
    </top_sas_users>
  </xsl:template>

</xsl:stylesheet>

SAS

proc xsl 
    in="C:\Path\To\Input.xml"
    out="C:\Path\To\Output.xml"
    xsl="C:\Path\To\XSLT_Script.xsl";
run;

libname mydata xml 'C:\Path\To\Output.xml' xmlmeta=schemadata;

data xml_data; 
    retain user link year_rep total_rep tag1 tag2 tag3; 
    set mydata.top_sas_users;       
run;

proc print data=xml_data; run;

SAS 数据集输出


推荐阅读