我在上一个问题(flattening XML to load via SSIS package)中尝试了解决方案,但这不起作用。我现在知道我需要做什么,但是我需要一些如何做的指导。
所以说我有以下XML结构:
<person id="1">
<name>John</name>
<surname>Smith</surname>
<age>25</age>
<comment>
<comment_id>1</comment_id>
<comment_text>Hello</comment_text>
</comment>
<comment>
<comment_id>2</comment_id>
<comment_text>Hello again!</comment_text>
</comment>
<somethingelse>
<id>1</id>
</somethingelse>
<comment>
<comment_id>3</comment_id>
<comment_text>Third Item</comment_text>
</comment>
</person>
<person id="2">
<name>John</name>
<surname>Smith</surname>
<age>25</age>
<somethingelse>
<id>1</id>
</somethingelse>
</person>
...
...
如果我要将它作为XML源加载到SSIS包中,我将基本上得到的是为每个元素创建的表,而不是获取结构化表输出,例如
我最终获得的是:
等...
我发现如果每个元素和所有内部元素的格式和一致性不同,我将得到上述异常,这使得它相当复杂,特别是如果我处理的是80 - 100+列。
不幸的是我无法修改生成这些报告的系统(Lotus Notes),因此我想知道我是否能够显式拥有一个能够对齐每个模板的XSLT模板人子元素(以及评论等子集合元素?除非有更快捷的方式重新排列所有内部元素。
似乎SSIS XML源需要一个非常一致的XML文件,意思是:如果 name 元素位于第1位,那么 name 元素>人父母必须在第1位。
如果某个父中某些元素缺失到另一个
感谢所有帮助!提前谢谢。
答案 0 :(得分:2)
根据我的理解,您需要<person>
子女的特定订单。看看以下XSLT是否接近你所追求的目标:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<!-- XSLT identity transformation -->
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="person">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="name"/>
<xsl:apply-templates select="surname"/>
<xsl:apply-templates select="age"/>
<xsl:apply-templates select="somethingelse"/>
<xsl:apply-templates select="comment"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<project>
<person id="1">
<name>John</name>
<surname>Smith</surname>
<age>25</age>
<somethingelse>
<id>1</id>
</somethingelse>
<comment>
<comment_id>1</comment_id>
<comment_text>Hello</comment_text>
</comment>
<comment>
<comment_id>2</comment_id>
<comment_text>Hello again!</comment_text>
</comment>
<comment>
<comment_id>3</comment_id>
<comment_text>Third Item</comment_text>
</comment>
</person>
<person id="2">
<name>John</name>
<surname>Smith</surname>
<age>25</age>
<somethingelse>
<id>1</id>
</somethingelse>
</person>
</project>
答案 1 :(得分:2)
如果您不想包含如何订购的手动定义,您可以按字母顺序排序。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="person">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="*">
<xsl:sort data-type="text" select="name()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这样输出顺序是可预测且稳定的,但<name>
例如会在<comment>
之后的中间某处结束。我不知道SSIS是否完全正确,但我想它应该是。
编辑:如果你想将依赖表(即包含子项而不是文本的元素)排序到底部......那么,<xsl:sort>
可以多次应用。
<xsl:template match="person">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="*">
<xsl:sort data-type="number" select="boolean(*)" />
<xsl:sort data-type="text" select="name()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
boolean(*)
有效地将“儿童”/“没有儿童”的事实转换为true
/ false
,而data-type="number"
/ 0
反过来(在数字背景下,归因于1
)表示为{{1}} / {{1}}。这样,纯文本元素就会在其他所有元素之前结束。