如何使用XSLT将父元素的值复制到多个子节点?

How to use XSLT to copy value of a parent element to multiple children nodes?

提问人:Eric Waggoner 提问时间:11/14/2023 更新时间:11/14/2023 访问量:32

问:

我有一个 XML 文件,需要转换以导入到财务系统。“位置”在开始时只被引用一次,然后是记录(通常有几百条),我已将其转换为借方或贷方,但我需要从文件顶部提取位置信息,以便将其列在每条记录中以进行导入。

源文件:

<?xml version='1.0' encoding="UTF-8"?>
<gldata>
    <FacilityData>
        <Corp>Fabrikam Group</Corp>
        <FacilityID>26</FacilityID>
        <CustomerLocationID>640</CustomerLocationID>
        <Region>PA</Region>
        <District>Springfield</District>
        <transaction>
            <EntryID>12345</EntryID>
            <TransactionDate>07-24-2023</TransactionDate>
            <ServiceDate>
            </ServiceDate>
            <TransactionType>40</TransactionType>
            <TransDescription>Desription Generic</TransDescription>
            <AccountNumber>1010-00</AccountNumber>
            <Currency>USD</Currency>
            <AccountType>A</AccountType>
            <BatchID>2351</BatchID>
            <TransactionDetail>
                <Amount>628.00</Amount>
                <Type>DRAmount</Type>
            </TransactionDetail>
        </transaction>
       </FacilityData>
</gldata>
.
.

我当前的 XSL:


<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="TransactionDetail">
    <xsl:element name="{Type}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

我需要什么:

<transaction>
    <EntryID>12345</EntryID>
    <TransactionDate>07-24-2023</TransactionDate>
    <ServiceDate>
    </ServiceDate>
    <TransactionType>40</TransactionType>
    <TransDescription>Desription Generic</TransDescription>
    <AccountNumber>1010-00</AccountNumber>
    <Currency>USD</Currency>
    <AccountType>A</AccountType>
    <BatchID>2351</BatchID>
    <TransactionDetail>
        <Amount>628.00</Amount>
        <Type>DRAmount</Type>
                <CustomerLocationID>640</CustomerLocationID>
    </TransactionDetail>
</transaction>

显然,我可以处理额外的信息,但我无法做任何事情来从表单顶部提取信息并将其复制到每条记录中。我确实在“TransactionDetail”下需要它,因为许多“Transaction”记录都有多个明细行,这些明细行作为单独的行项导入。

任何帮助都非常感谢!我不擅长 XML,但我觉得我做得比它需要的要难得多。

XML XSLT

评论


答:

1赞 michael.hor257k 11/14/2023 #1

您可以执行以下操作:

<xsl:template match="TransactionDetail">
    <xsl:element name="{Type}">
        <xsl:apply-templates/>
        <xsl:copy-of select="ancestor::FacilityData/CustomerLocationID"/>
    </xsl:element>
</xsl:template>

更有效的方法可能是在级别检索一次,并将其存储在变量或要在级别使用的参数中。CustomerLocationIDFacilityDataTransactionDetail

如果仅限于 XSLT 1.0,则如下所示:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform with pass-thru param -->
<xsl:template match="@*|node()">
    <xsl:param name="custLocID"/>
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:with-param name="custLocID" select="$custLocID"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="FacilityData">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:with-param name="custLocID" select="CustomerLocationID"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="TransactionDetail">
    <xsl:param name="custLocID"/>
    <xsl:element name="{Type}">
        <xsl:apply-templates/>
        <xsl:copy-of select="$custLocID"/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

评论

0赞 Eric Waggoner 11/14/2023
呃,祖先是我找不到的,也是为什么我一直无法跳回那么多关卡的原因。我不太担心效率,因为这些文件不是太大的文件,而且它们有可能最终分散在一个文件中的多个设施中,所以我认为从长远来看,我最好避免变量并不得不重置它们等。非常感谢您的快速回复!
0赞 michael.hor257k 11/14/2023
它只有 2 级,所以你可以做到.--- 没有必要重置变量(即使你愿意,你也不能重置,因为 XSLT 变量是不可变的)。您可以拥有任意数量的设施;每个设施都会将自己的参数传递给其后代。<xsl:copy-of select="../../CustomerLocationID"/>