使用 XSLT 展平 XML 嵌套节点
flatten XML nested node with XSLT
目标:将 CRM 动态数据 xml 文件导入 SSIS XML 转换块。
SSIS 限制:
- 只有一个命名空间
- 无嵌套节点
- 删除"un necessary"link节点
简化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 完全删除了名称空间。但是我正在尝试 transform/flatten 每个 type="Microsoft.Crm.Sdk.Data.Services.EntityReference" 的节点只有一个 guid 值
...
<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>
...
到目前为止没有任何运气......
任何帮助表示赞赏
您似乎在避免尝试引用 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,link 元素实际上将与 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>
目标:将 CRM 动态数据 xml 文件导入 SSIS XML 转换块。
SSIS 限制:
- 只有一个命名空间
- 无嵌套节点
- 删除"un necessary"link节点
简化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 完全删除了名称空间。但是我正在尝试 transform/flatten 每个 type="Microsoft.Crm.Sdk.Data.Services.EntityReference" 的节点只有一个 guid 值
...
<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>
...
到目前为止没有任何运气...... 任何帮助表示赞赏
您似乎在避免尝试引用 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,link 元素实际上将与 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>