Xslt 循环并将子节点拆分为多个子节点
这是我需要使用XSLT2.0转换的输入XMLXslt 循环并将子节点拆分为多个子节点,xslt,xslt-2.0,Xslt,Xslt 2.0,这是我需要使用XSLT2.0转换的输入XML <?xml version="1.0" encoding="UTF-8"?> <Workers> <Worker> <id>1234</id> <loc>New York</loc> <Days>1</Days> <StartDate>2019-01-26<
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<id>1234</id>
<loc>New York</loc>
<Days>1</Days>
<StartDate>2019-01-26</StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<Batch>A</Batch>
<Days>3</Days>
<Units>2</Units>
<StartDate>2019-02-01</StartDate>
</Worker>
</Workers>
电流输出
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<id>1234</id>
<loc>New York</loc>
<Days>1</Days>
<StartDate>2019-01-26</StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<RecordNumber>1</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>2019-02-02</StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<RecordNumber>2</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>2019-02-03</StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<RecordNumber>3</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>2019-02-04</StartDate>
</Worker>
</Workers>
预期产量
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<id>1234</id>
<loc>New York</loc>
<Days>1</Days>
<StartDate>2019-01-26</StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<RecordNumber>1</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>2019-02-01</StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<RecordNumber>2</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>2019-02-02/StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<RecordNumber>3</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>2019-02-03</StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<RecordNumber>1</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>2019-02-01</StartDate>
</Worker>
<Worker>
<id>2345</id>
<loc>Boston</loc>
<RecordNumber>2</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>2019-02-02/StartDate>
</Worker>
</Workers>
我的要求是
a。如果子节点中不存在元素,则应复制XML中显示的子节点。在上面的XML中,第一个worker子节点应该按照它在XML中的显示进行复制,因为它没有元素
b。若元素存在于子节点中,则需要根据以下两个条件将该子节点拆分为多个子节点
一,。子节点的数量需要创建的次数与元素的值相同。在本例中,值为3,因此需要创建3个子节点,并且这些子节点中的每一个子节点都应该增加1,并创建一个新元素,该元素应该包含该循环的值
二,。再次需要根据元素的值拆分子节点。在上面的XML中,是2,所以需要创建两倍的子节点,并且每次创建和创建一个应该保存该循环值的新元素时,子节点需要增加一倍
当前XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:functx="http://www.functx.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Workers/Worker[exists(Batch)]">
<xsl:variable name="start" select="1"/>
<xsl:variable name="counter" select="Days"/>
<xsl:variable name="Records" select="."/>
<xsl:for-each select="$start to $counter">
<xsl:apply-templates select="$Records" mode="replicate">
<xsl:with-param name="data" select="."/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="Workers/Worker" mode="replicate">
<xsl:param name="data"/>
<Worker>
<id>
<xsl:value-of select="id"/>
</id>
<loc>
<xsl:value-of select="loc"/>
</loc>
<RecordNumber>
<xsl:value-of select="$data"/>
</RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>
<xsl:value-of select="xs:date(StartDate) + xs:dayTimeDuration('P1D') * $data"/>
</StartDate>
</Worker>
</xsl:template>
</xsl:stylesheet>
问题:
的值错误-似乎缺少实际值
XSLT根本没有基于拆分子节点
子节点应该在预期输出中出现6次,而我现在只看到4次
有人能帮我解决这个问题吗
感谢您的预期输出,我发现您需要一个序列中的两个循环: 第一次执行的天数, 第二个执行单元的次数, 从输入日期开始的连续日期的两个 还请注意,在for-each循环中,上下文项会发生更改,因此 对于两种情况,对于每个循环,上下文项是当前的循环数 执行,采取形式选择属性 这就是为什么在每个循环中,当调用工作模板时, dayNo参数以点形式给出,currElem为 只是调用了Worker[Batch]模板的元素 就输出StartDate而言,dayTimeDuration必须是 添加$dayNo-1次 其他有用的补充/更改包括: 一开始,情况会好一些 输出的缩进。 -将源元素复制到输出的较短形式。 还值得注意的是,它运行更快,消耗更多 内存更少。 我删除了一些只使用了一次的变量。 您使用了一个名为data的变量。我觉得这个名字太笼统了, 所以我把它改为currElem当前元素。 因此,整个脚本可以如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Worker[Batch]">
<xsl:variable name="currElem" select="."/>
<xsl:for-each select="1 to Days">
<xsl:apply-templates select="$currElem" mode="replicate">
<xsl:with-param name="dayNo" select="."/>
</xsl:apply-templates>
</xsl:for-each>
<xsl:for-each select="1 to Units">
<xsl:apply-templates select="$currElem" mode="replicate">
<xsl:with-param name="dayNo" select="."/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="Worker" mode="replicate">
<xsl:param name="dayNo"/>
<Worker>
<xsl:sequence select="id, loc"/>
<RecordNumber><xsl:value-of select="$dayNo"/></RecordNumber>
<WorkerDays>1</WorkerDays>
<StartDate>
<xsl:value-of select="xs:date(StartDate) + xs:dayTimeDuration('P1D') * ($dayNo - 1)"/>
</StartDate>
</Worker>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
有关工作示例,请参见
如果需要,第一个版本正在下载中
比较一下。谢谢你,瓦迪乌波。当我试图理解您的代码时,我发现它返回的输出有问题。的值为2,所以只需创建两次元素。现在它返回了3次。预期输出应该只有6个节点。这是每个外部循环的问题吗?您的输入XML包含2次执行外部循环的次数和3次执行连续日期的内部循环的次数。因此,我的脚本生成了预期的结果。另一方面,多次生成完全相同的内容有点奇怪,但我就是这样理解你的问题的。或者也许外环的结果应该在某些方面有所不同?很抱歉让您混淆了我的要求。让我举一个例子来说明我的要求。如果值为9且为2,则需要创建11次元素。。由于您所述的原因,现在创建了18次-外部循环执行的次数为。另一个例子。。如果单位为5,天数为10-15倍,则需要创建Worker元素。。同一内容需要多次生成的原因是下游系统的要求,因为它们需要逐个处理RecordNumber和StartDates。根据您最近评论中的解释,我更正了解决方案。现在应该没事了。