从一个XML文件到另一个XML文件获取不断增加的ID
一般来说,我有以下情况: 一个数据库由3000个文件组成。每个文件平均由500个结构相同的节点组成。每个节点的顶级父元素“Document”具有唯一的ID(非数字) 任务:从一个XML文件到另一个XML文件获取不断增加的ID,xml,xslt,ssis,Xml,Xslt,Ssis,一般来说,我有以下情况: 一个数据库由3000个文件组成。每个文件平均由500个结构相同的节点组成。每个节点的顶级父元素“Document”具有唯一的ID(非数字) 任务: 文档及其节点中的所有子项/子项必须获得额外的数字ID(递增计数文档节点) ID必须具有可分配的起始范围。ID随步骤+1递增。(如350001、350002等) (问题的本质)ID计数器不仅在一个XML文件级别上继续工作,而且在整个文件集上也继续工作 也许,我认为,我的问题并不意味着我的具体代码,而是要求一个方法模型或一组
- 文档及其节点中的所有子项/子项必须获得额外的数字ID(递增计数文档节点)
- ID必须具有可分配的起始范围。ID随步骤+1递增。(如350001、350002等)
- (问题的本质)ID计数器不仅在一个XML文件级别上继续工作,而且在整个文件集上也继续工作
- 我将非常感谢所有建议使用XSLT语言的解决方案
- 或者,作为替代或补充方式,通过SSIS工具
UPD:或者通过xslt 3中的其他集成的非xslt SSIS工具,您可以使用
xsl:iterate
和累加器来完成:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes"
version="3.0">
<xsl:param name="documents" as="document-node()*">
<xsl:iterate select="1 to 5">
<xsl:document>
<root>
<xsl:iterate select="1 to 5">
<section>
<xsl:iterate select="1 to 20">
<foo>foo {.}</foo>
</xsl:iterate>
</section>
</xsl:iterate>
</root>
</xsl:document>
</xsl:iterate>
</xsl:param>
<xsl:param name="start-id" as="xs:integer" select="35000"/>
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:accumulator name="element-count" as="xs:integer" initial-value="0">
<xsl:accumulator-rule match="*" select="$value + 1"/>
</xsl:accumulator>
<xsl:template match="/" name="xsl:initial-template">
<xsl:iterate select="$documents">
<xsl:param name="start-id" select="$start-id"/>
<xsl:apply-templates select="node()">
<xsl:with-param name="start-id" select="$start-id" tunnel="yes"/>
</xsl:apply-templates>
<xsl:next-iteration>
<xsl:with-param name="start-id" select="$start-id + accumulator-after('element-count')"/>
</xsl:next-iteration>
</xsl:iterate>
</xsl:template>
<xsl:template match="*">
<xsl:param name="start-id" tunnel="yes"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="collection-count" select="$start-id + accumulator-before('element-count')"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
而不是
<xsl:apply-templates select="node()">
<xsl:with-param name="start-id" select="$start-id" tunnel="yes"/>
</xsl:apply-templates>
目前还没有流媒体,因为我目前不确定如何从流媒体文档中传递值,稍后我将查看是否可以解决该问题。但无论如何,流媒体都需要Saxon EE。那是哪个数据库?它可以使用哪个XSLT处理器?数据库由XML文件组成。但是你可以忽略这是一个数据库,忘记这个词。重要的是,它是一系列XML文件,需要进行大量操作。问题是-在多大程度上这只能在XSLT语言内完成,从一个文件循环到另一个文件。从第1卷到第2卷的任何标准XSLT处理器,或者如果某些解决方案可能仅来自3.0-我将欢迎,并且也是这个变体)谢谢!我将尝试实现此代码。难道你不知道微软的SSIS支持XSLT 3.0吗?微软自己的XSLT处理器,如各种MSXML版本和.NET版本,如XslCompiledTransform,只支持XSLT 1.0。我不知道SSIS是否允许插入XSLT 2或3处理器,如Saxon 9或XmlPrime或Altova Raptor。使用哪种自由软件XSLT工具来处理许多文件(支持3.0)。Saxon 9.9适用于.NET平台(在NuGet和Sourceforge上)和Java平台(在Maven和Sourceforge上)正如Martin Honnen已经指出的,SSIS开箱即用仅支持XSLT v.1.0,尽管SSIS脚本任务允许启动任何.Net代码。所以,结合Saxon 9.9.Net版本和SSIS脚本任务将提供一个解决方案。
<xsl:result-document href="{document-uri()}-update.xml">
<xsl:apply-templates select="node()">
<xsl:with-param name="start-id" select="$start-id" tunnel="yes"/>
</xsl:apply-templates>
</xsl:result-document>
<xsl:apply-templates select="node()">
<xsl:with-param name="start-id" select="$start-id" tunnel="yes"/>
</xsl:apply-templates>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" expand-text="yes"
version="3.0">
<xsl:param name="input-uris" select="uri-collection('?select=sample-*.xml')"/>
<xsl:param name="start-id" as="xs:integer" select="35000"/>
<xsl:mode on-no-match="shallow-copy" streamable="yes" use-accumulators="element-count"/>
<xsl:accumulator name="element-count" as="xs:integer" initial-value="0" streamable="yes">
<xsl:accumulator-rule match="*" select="$value + 1"/>
</xsl:accumulator>
<xsl:template match="/" name="xsl:initial-template">
<xsl:iterate select="$input-uris ! doc(.)">
<xsl:param name="start-id" select="$start-id"/>
<xsl:result-document href="updated-xmls/{tokenize(document-uri(), '/')[last()]}">
<xsl:apply-templates select="node()">
<xsl:with-param name="start-id" select="$start-id" tunnel="yes"/>
</xsl:apply-templates>
</xsl:result-document>
<xsl:next-iteration>
<xsl:with-param name="start-id"
select="$start-id + accumulator-after('element-count')"/>
</xsl:next-iteration>
</xsl:iterate>
</xsl:template>
<xsl:template match="*">
<xsl:param name="start-id" tunnel="yes"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="collection-count"
select="$start-id + accumulator-before('element-count')"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>