【发布时间】:2017-06-21 11:36:22
【问题描述】:
我有一些 xml,其中一部分看起来像这样:
<BasicInfo>
<Foo>80</Foo>
<Bar>
</Bar>
</BasicInfo>
我想用单个自闭合节点替换所有空节点打开和关闭对(如上面的<Bar>),以提供如下内容:
<BasicInfo>
<Foo>80</Foo>
<Bar />
</BasicInfo>
我知道在xml中,两者是等价的,xslt会选择它想如何输出空节点等等,但是我有很多空节点并且两种解释的预期文件大小差异很大足以值得担心;我希望尽可能高效地存储 xml。
上面的 xml 是从 SQL Server 创建的,然后使用另一个 XSLT 进行转换,该 XSLT 删除了 SQL Server 2008 留下的所有“xsi:nil”值和 xmlns 声明:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<xsl:template match="@*[local-name(.)='noNamespaceSchemaLocation']" />
<xsl:template xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" match="@xsi:nil" />
</xsl:stylesheet>
正是这个样式表留下了开闭对 - 有没有办法强迫它留下自闭节点,或者让一个新的 xslt 自己产生这种效果?
遗憾的是,删除节点不是一种选择:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />
<!--Remove all the empty nodes-->
<!--copy nodes-->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!--match only those with no contents at all-->
<xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']" />
<!--now check all those that have existing but empty children and don't return the children if they are empty-->
<xsl:template match="*">
<xsl:copy>
<xsl:if test="descendant::text()">
<xsl:apply-templates select="node()" />
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
但这是我得到的最接近的。我发现其他人在问这个问题,但我对 xslt 的了解不足意味着我无法根据自己的需要更改解决方案(花了很长时间才解决上述问题!)。似乎遵循规范化空间的方法是要走的路?非常感谢您的帮助!
注意。 xml 由 SQL Server 2008 R2 使用FOR XML PATH 生成,XSLT 脚本存储在服务器上的 xml 列中; SSIS 2008 中操作数类型为 XSLT 的 XML 任务应用了转换。
【问题讨论】:
-
此 XML 的创建是否在您的控制之下?
-
是的,需要注意的是我使用 SQL Server 来制作它。
-
<xsl:strip-space elements="*"/>应该这样做。您是否正在使用XSLCompiledTransform执行转换?您可能需要将XSLCompiledTransform.OutputSettings传递给XmlWriter.Create,以便XmlWriter使用您在样式表中定义的输出设置。 -
我最初对
<xsl:strip-space elements="*"/>也有同样的想法,但我认为我一定是错的。我不知道我是否在使用 XSLCompiledTransform...它只是 SSIS 中的一个 XML 任务,将一个变量作为我的 xml 文件,另一个作为 XSLT。我是不是应该改用脚本任务,照你说的做? -
您能否展示一个首先生成 XML 的查询?很有可能,它可以被修改,这样它就可以产生这些讨厌的节点了。
标签: sql-server xml sql-server-2008 xslt ssis-2008