将父节点复制到根以创建多个项目
Copying the parents nodes upto the root to create multiple items
我是 XSLT 的新手,我正在处理一个棘手的 xml 转换需求。
我的来源 xml 如下所述。
<Level_0>
<Level_1>
<Level_2>
<Level_3>hello</Level_3>
<Level_4>
<Header>
<Value>SomeValue</Value>
</Header>
<SalesInvoice>
<Item>
<Detail>
<Position>1</Position>
</Detail>
</Item>
</SalesInvoice>
<SalesInvoice>
<Item>
<Detail>
<Position>2</Position>
</Detail>
</Item>
</SalesInvoice>
<SalesInvoice>
<Item>
<Detail>
<Position>3</Position>
</Detail>
</Item>
</SalesInvoice>
</Level_4>
</Level_2>
</Level_1>
</Level_0>
要求 - 我需要让每个项目的父项达到 level_1,这意味着输出应该如下所述。基本上,应该为 level_1.
中的每个项目重复所有内容
<Level_0>
<Level_1>
<Level_2>
<Level_3>hello</Level_3>
<Level_4>
<Header>
<Value>SomeValue</Value>
</Header>
<SalesInvoice>
<Item>
<Detail>
<Position>1</Position>
</Detail>
</Item>
</SalesInvoice>
</Level_4>
</Level_2>
</Level_1>
<Level_1>
<Level_2>
<Level_3>hello</Level_3>
<Level_4>
<Header>
<Value>SomeValue</Value>
</Header>
<SalesInvoice>
<Item>
<Detail>
<Position>2</Position>
</Detail>
</Item>
</SalesInvoice>
</Level_4>
</Level_2>
</Level_1>
<Level_1>
<Level_2>
<Level_3>hello</Level_3>
<Level_4>
<Header>
<Value>SomeValue</Value>
</Header>
<SalesInvoice>
<Item>
<Detail>
<Position>3</Position>
</Detail>
</Item>
</SalesInvoice>
</Level_4>
</Level_2>
</Level_1>
</Level_0>
XSLT 我试过了。但是我得到了奇怪的输出。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="SalesInvoice">
<NewInvoice>
<xsl:copy-of select="../../../../Level_1/descendant::*[not(name()='SalesInvoice' or ancestor::SalesInvoice)]"/>
<xsl:copy-of select="."/>
</NewInvoice>
</xsl:template>
</xsl:stylesheet>
这是处理它的一种方法。对于每个 SalesInvoice
进程,apply-templates 从它的 Level_1
开始,但将 SalesInvoice
作为参数传递(我使用 @tunnel,但您可以明确定义参数并在每个模板的每个级别传递它)。在匹配 SalesInvoice
的模板中,仅复制 $invoice-context
的内容,否则将被丢弃。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Level_0">
<xsl:copy>
<xsl:for-each select="//SalesInvoice">
<xsl:apply-templates select="ancestor::Level_1" mode="repeat">
<xsl:with-param name="invoice-context" select="." tunnel="yes"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="repeat">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="repeat"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SalesInvoice" mode="repeat">
<xsl:param name="invoice-context" tunnel="yes"/>
<xsl:if test="generate-id(.) eq generate-id($invoice-context)">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
我是 XSLT 的新手,我正在处理一个棘手的 xml 转换需求。 我的来源 xml 如下所述。
<Level_0>
<Level_1>
<Level_2>
<Level_3>hello</Level_3>
<Level_4>
<Header>
<Value>SomeValue</Value>
</Header>
<SalesInvoice>
<Item>
<Detail>
<Position>1</Position>
</Detail>
</Item>
</SalesInvoice>
<SalesInvoice>
<Item>
<Detail>
<Position>2</Position>
</Detail>
</Item>
</SalesInvoice>
<SalesInvoice>
<Item>
<Detail>
<Position>3</Position>
</Detail>
</Item>
</SalesInvoice>
</Level_4>
</Level_2>
</Level_1>
</Level_0>
要求 - 我需要让每个项目的父项达到 level_1,这意味着输出应该如下所述。基本上,应该为 level_1.
中的每个项目重复所有内容<Level_0>
<Level_1>
<Level_2>
<Level_3>hello</Level_3>
<Level_4>
<Header>
<Value>SomeValue</Value>
</Header>
<SalesInvoice>
<Item>
<Detail>
<Position>1</Position>
</Detail>
</Item>
</SalesInvoice>
</Level_4>
</Level_2>
</Level_1>
<Level_1>
<Level_2>
<Level_3>hello</Level_3>
<Level_4>
<Header>
<Value>SomeValue</Value>
</Header>
<SalesInvoice>
<Item>
<Detail>
<Position>2</Position>
</Detail>
</Item>
</SalesInvoice>
</Level_4>
</Level_2>
</Level_1>
<Level_1>
<Level_2>
<Level_3>hello</Level_3>
<Level_4>
<Header>
<Value>SomeValue</Value>
</Header>
<SalesInvoice>
<Item>
<Detail>
<Position>3</Position>
</Detail>
</Item>
</SalesInvoice>
</Level_4>
</Level_2>
</Level_1>
</Level_0>
XSLT 我试过了。但是我得到了奇怪的输出。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="SalesInvoice">
<NewInvoice>
<xsl:copy-of select="../../../../Level_1/descendant::*[not(name()='SalesInvoice' or ancestor::SalesInvoice)]"/>
<xsl:copy-of select="."/>
</NewInvoice>
</xsl:template>
</xsl:stylesheet>
这是处理它的一种方法。对于每个 SalesInvoice
进程,apply-templates 从它的 Level_1
开始,但将 SalesInvoice
作为参数传递(我使用 @tunnel,但您可以明确定义参数并在每个模板的每个级别传递它)。在匹配 SalesInvoice
的模板中,仅复制 $invoice-context
的内容,否则将被丢弃。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Level_0">
<xsl:copy>
<xsl:for-each select="//SalesInvoice">
<xsl:apply-templates select="ancestor::Level_1" mode="repeat">
<xsl:with-param name="invoice-context" select="." tunnel="yes"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="repeat">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="repeat"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SalesInvoice" mode="repeat">
<xsl:param name="invoice-context" tunnel="yes"/>
<xsl:if test="generate-id(.) eq generate-id($invoice-context)">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>