使用XSLT展平XML嵌套节点

时间:2016-03-16 15:09:39

标签: xml xslt ssis dynamics-crm

目标:将CRM动态odata xml文件导入SSIS XML转换块。

SSIS约束:

  • 只有一个名称空间
  • 没有嵌套节点
  • 删除“不必要的”链接节点

简化的xml源

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="https://XXXXXXXXXX/XRMServices/2011/OrganizationData.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title type="text">allianceSet</title>
  <entry>
    <link rel="edit" title="be_alliance" href="be_allianceSet(guid'429352cb-deca-e311-80c0-00155d5682af')" />
    <link rel="XXXX" type="application/atom+xml;type=entry" title="lk_be_alliance_createdby" href="be_allianceSet/lk_be_alliance_createdby" />
    <link rel="XXXX" type="application/atom+xml;type=entry" title="lk_be_alliance_createdonbehalfby" href="be_allianceSet(/lk_be_alliance_createdonbehalfby" />
    <content type="application/xml">
      <m:properties>
        <d:ModifiedOn m:type="Edm.DateTime">2015-10-30T13:06:31Z</d:ModifiedOn>
        <d:CreatedBy m:type="Microsoft.Crm.Sdk.Data.Services.EntityReference" m:null="true">
          <d:Id m:type="Edm.Guid">40f20074-ede3-48cc-aafc-750a1275b99b</d:Id>
          <d:LogicalName>systemuser</d:LogicalName>
        </d:CreatedBy>
        <d:statecode m:type="Microsoft.Crm.Sdk.Data.Services.OptionSetValue">
          <d:Value m:type="Edm.Int32">0</d:Value>
        </d:statecode>
      </m:properties>
    </content>
  </entry>
</feed>

XSL输入1.0

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

    <xsl:template match="*[name() != 'link']">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <!-- template to copy attributes -->
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

以上xsl完全删除命名空间。但是我试图只用一个guid值来转换/压平type =“Microsoft.Crm.Sdk.Data.Services.EntityReference”的每个节点

...    
<CreatedBy type="Microsoft.Crm.Sdk.Data.Services.EntityReference" null="true">
    <Id type="Edm.Guid">40f20074-ede3-48cc-aafc-750a1275b99b</Id>
    <LogicalName>systemuser</LogicalName>
    </CreatedBy>
...

...
    <CreatedBy>40f20074-ede3-48cc-aafc-750a1275b99b</CreatedBy>
...
到目前为止没有运气...... 任何帮助赞赏

1 个答案:

答案 0 :(得分:1)

看起来您正在避免尝试引用XSLT中的任何特定命名空间。如果是这样,要将节点与类型属性“Microsoft.Crm.Sdk.Data.Services.EntityReference”匹配,您将得到如下模板匹配:

<xsl:template match="*[@*[local-name() = 'type']='Microsoft.Crm.Sdk.Data.Services.EntityReference']">

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="*[local-name() = 'link']" />

    <xsl:template match="*[@*[local-name() = 'type']='Microsoft.Crm.Sdk.Data.Services.EntityReference']">
        <xsl:element name="{local-name()}">
            <xsl:value-of select="*[local-name() = 'Id']" />
        </xsl:element>
    </xsl:template>

    <!-- template to copy attributes -->
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

请注意我是如何创建一个单独的模板来删除link元素的。使用当前的XSLT,链接元素实际上将与XSLT的内置模板匹配,如果有的话,它将输出link下的任何文本节点(可能不适合您,但可能更好)代码)。

当然,如果你一直在处理具有相同命名空间的XML文档,你可以在你的XSLT中引用它们,就像这样,这有点整洁:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" 
    xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
    xmlns:atom="http://www.w3.org/2005/Atom">

    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="atom:link" />

    <xsl:template match="*[@m:type='Microsoft.Crm.Sdk.Data.Services.EntityReference']">
        <xsl:element name="{local-name()}">
            <xsl:value-of select="d:Id" />
        </xsl:element>
    </xsl:template>

    <!-- template to copy attributes -->
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>