Sql server 使用XSLT将层次xml转换为平面xml
我有如下结构的xmlSql server 使用XSLT将层次xml转换为平面xml,sql-server,sql-server-2008,xslt,reporting-services,Sql Server,Sql Server 2008,Xslt,Reporting Services,我有如下结构的xml <root> <PNode> <node1> <node1Child>data</node1Child> <node2Child>data</node2Child> </node1> </PNode> <SecondNode> <node1> <node1Child&
<root>
<PNode>
<node1>
<node1Child>data</node1Child>
<node2Child>data</node2Child>
</node1>
</PNode>
<SecondNode>
<node1>
<node1Child>
<child>data</child>
</node1Child>
</node1>
</SecondNode>
</root>
数据
数据
数据
我希望使用genric xslt输出,因为我有很多xml要转换成这种格式
<root>
<Pnode-node1-node1Child>data</Pnode-node1-node1Child>
<Pnode-node1-node2Child>data</Pnode-node1-node2Child>
<SecondNode-node1-node1child-child>data</SecondNode-node1-node1child-child>
</root>
数据
数据
数据
它可以更深或更浅。我可以用XSLT吗?请给出一些例子或参考资料
我想从SQLServer2K8R2 rdl生成PDF。因为rdl不接受嵌套的xml,所以需要将其展平。在模板中,测试子节点 如果存在子节点,则将上一个参数值传递给它,该参数值与此元素的名称连接在一起 如果只有#text,则使用参数作为其名称输出新元素,并将其内容设置为#text,给定此输入:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<PNode>
<node1>
<node1Child>data</node1Child>
<node2Child>data</node2Child>
</node1>
</PNode>
<SecondNode>
<node1>
<node1Child>
<child>data</child>
</node1Child>
</node1>
</SecondNode>
</root>
数据
数据
数据
以下样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" method="xml"/>
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates select="*" mode="flatten"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[normalize-space(text())]" mode="flatten">
<xsl:param name="name-prefix" select="''"/>
<xsl:variable name="name">
<xsl:call-template name="construct-name">
<xsl:with-param name="name-prefix" select="$name-prefix"/>
</xsl:call-template>
</xsl:variable>
<xsl:element name="{$name}">
<xsl:apply-templates select="text()"/>
</xsl:element>
<xsl:apply-templates select="node()" mode="flatten">
<xsl:with-param name="name-prefix" select="$name"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*[not(normalize-space(text()))]" mode="flatten">
<xsl:param name="name-prefix" select="''"/>
<xsl:variable name="prefix">
<xsl:call-template name="construct-name">
<xsl:with-param name="name-prefix" select="$name-prefix"/>
</xsl:call-template>
</xsl:variable>
<xsl:apply-templates select="node()" mode="flatten">
<xsl:with-param name="name-prefix" select="$prefix"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="construct-name">
<xsl:param name="name-prefix"/>
<xsl:choose>
<xsl:when test="$name-prefix">
<xsl:value-of select="concat($name-prefix, '-', local-name(.))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="local-name(.)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="text()" mode="flatten"/>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:param name="pName"/>
<xsl:apply-templates>
<xsl:with-param name="pName" select="concat($pName,name(),'-')"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="text()">
<xsl:param name="pName"/>
<xsl:element name="{substring($pName,1,string-length($pName)-1)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
产生想要的结果:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<PNode-node1-node1Child>data</PNode-node1-node1Child>
<PNode-node1-node2Child>data</PNode-node1-node2Child>
<SecondNode-node1-node1Child-child>data</SecondNode-node1-node1Child-child>
</root>
数据
数据
数据
此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" method="xml"/>
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates select="*" mode="flatten"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[normalize-space(text())]" mode="flatten">
<xsl:param name="name-prefix" select="''"/>
<xsl:variable name="name">
<xsl:call-template name="construct-name">
<xsl:with-param name="name-prefix" select="$name-prefix"/>
</xsl:call-template>
</xsl:variable>
<xsl:element name="{$name}">
<xsl:apply-templates select="text()"/>
</xsl:element>
<xsl:apply-templates select="node()" mode="flatten">
<xsl:with-param name="name-prefix" select="$name"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*[not(normalize-space(text()))]" mode="flatten">
<xsl:param name="name-prefix" select="''"/>
<xsl:variable name="prefix">
<xsl:call-template name="construct-name">
<xsl:with-param name="name-prefix" select="$name-prefix"/>
</xsl:call-template>
</xsl:variable>
<xsl:apply-templates select="node()" mode="flatten">
<xsl:with-param name="name-prefix" select="$prefix"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="construct-name">
<xsl:param name="name-prefix"/>
<xsl:choose>
<xsl:when test="$name-prefix">
<xsl:value-of select="concat($name-prefix, '-', local-name(.))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="local-name(.)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="text()" mode="flatten"/>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:param name="pName"/>
<xsl:apply-templates>
<xsl:with-param name="pName" select="concat($pName,name(),'-')"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="text()">
<xsl:param name="pName"/>
<xsl:element name="{substring($pName,1,string-length($pName)-1)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
输出:
<root>
<PNode-node1-node1Child>data</PNode-node1-node1Child>
<PNode-node1-node2Child>data</PNode-node1-node2Child>
<SecondNode-node1-node1Child-child>data</SecondNode-node1-node1Child-child>
</root>
数据
数据
数据
更新:如果可能存在empy节点
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:param name="pName"/>
<xsl:apply-templates>
<xsl:with-param name="pName" select="concat($pName,name(),'-')"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*[not(*)]">
<xsl:param name="pName"/>
<xsl:element name="{$pName}{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
注意:匹配最里面的元素。此转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="text()">
<xsl:variable name="vCompName">
<xsl:for-each select="ancestor::*[not(position() =last())]">
<xsl:value-of select="translate(name(), ':', '_')"/>
<xsl:if test="not(position()=last())">-</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:element name="{$vCompName}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
-
应用于提供的XML文档时:
<root>
<PNode>
<node1>
<node1Child>data</node1Child>
<node2Child>data</node2Child>
</node1>
</PNode>
<SecondNode>
<node1>
<node1Child>
<child>data</child>
</node1Child>
</node1>
</SecondNode>
</root>
<root>
<PNode-node1-node1Child>data</PNode-node1-node1Child>
<PNode-node1-node2Child>data</PNode-node1-node2Child>
<SecondNode-node1-node1Child-child>data</SecondNode-node1-node1Child-child>
</root>
数据
数据
数据
生成所需的正确结果:
<root>
<PNode>
<node1>
<node1Child>data</node1Child>
<node2Child>data</node2Child>
</node1>
</PNode>
<SecondNode>
<node1>
<node1Child>
<child>data</child>
</node1Child>
</node1>
</SecondNode>
</root>
<root>
<PNode-node1-node1Child>data</PNode-node1-node1Child>
<PNode-node1-node2Child>data</PNode-node1-node2Child>
<SecondNode-node1-node1Child-child>data</SecondNode-node1-node1Child-child>
</root>
数据
数据
数据
说明:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="text()">
<xsl:variable name="vCompName">
<xsl:for-each select="ancestor::*[not(position() =last())]">
<xsl:value-of select="translate(name(), ':', '_')"/>
<xsl:if test="not(position()=last())">-</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:element name="{$vCompName}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
根元素
顶元素包装文档外,只有一个模板。它匹配任何非纯空白文本节点祖先::
中的最后一个)之外,所有元素祖先的节点集都是用'-'
字符连接的字符串,并且元素是以该字符串作为名称构造的:'
字符都被下划线字符替换。这样,如果某些名称中有名称空间前缀,则转换不会产生无效的复合名称假设你的意思是好问题,+1。请参阅我的答案,以获得完整、简短且简单的解决方案。还提供了广泛的解释。转换是健壮的,在名称空间和前缀名称的情况下可以工作。@Alex Nikolaenkov这不是给我节点。输出datadatadata@Jagan,如果使用浏览器查看结果,请使用
查看源代码检查xml文档。我已经用XalanXSLT处理器验证了我的样式表。嘿,alex,它不起作用了,我试过使用XMLSpy、StylusStuio和c#代码。只提供数据的节点根本不会出现。我刚得到数据。请重新检查。@Techmaster,请指定您的XSLT处理器
。我正在使用C#中的代码进行处理。我还尝试使用XML间谍工具。所有人都只提供数据。Thx.+1是一个好答案。顺便说一句,如果test
expr用一个额外的括号括起来,为什么你的?@Flack:谢谢。至于额外的括号:我开始用C#if
语句编写它,然后注意到我在做什么,并将它放在test
属性:)中。“这会简化它。”亚历杭德罗回答得很小,很完美。非常感谢。@Alejandro,您好,match=“text()”忽略空标记,我也需要包含它。e、 g如果SecondNode-node1-node1child-child为空,则此xlst将不包括在最终xml中。任何调整。