1

我有 XML 是这样的:

<ENVELOPE>
    <DSPACCNAME>
        <DSPDISPNAME>Opening Stock</DSPDISPNAME>
    </DSPACCNAME>
    <PLAMT>
        <PLSUBAMT/>
        <BSMAINAMT>-44912711.35</BSMAINAMT>
    </PLAMT>
    <BSNAME>
        <DSPACCNAME>
            <DSPDISPNAME>Stock-in-Hand-Accesories(KPM)</DSPDISPNAME>
        </DSPACCNAME>
    </BSNAME>
    <BSAMT>
        <BSSUBAMT>-15750.01</BSSUBAMT>
        <BSMAINAMT/>
    </BSAMT>
    <BSNAME>
        <DSPACCNAME>
            <DSPDISPNAME>Stock-in-Hand-Accesories(KVM)</DSPDISPNAME>
        </DSPACCNAME>
    </BSNAME>
    <BSAMT>
        <BSSUBAMT>-16750.01</BSSUBAMT>
        <BSMAINAMT/>
    </BSAMT>
    <DSPACCNAME>
        <DSPDISPNAME>Closing Stock</DSPDISPNAME>
    </DSPACCNAME>
    <BSNAME>
        <DSPACCNAME>
            <DSPDISPNAME>Stock-in-Hand-Accesories(KPM)</DSPDISPNAME>
        </DSPACCNAME>
    </BSNAME>
    <BSAMT>
        <BSSUBAMT>-54750.01</BSSUBAMT>
        <BSMAINAMT/>
    </BSAMT>
    <BSNAME>
        <DSPACCNAME>
            <DSPDISPNAME>Stock-in-Hand-Accesories(KRM)</DSPDISPNAME>
        </DSPACCNAME>
    </BSNAME>
    <BSAMT>
        <BSSUBAMT>-74750.01</BSSUBAMT>
        <BSMAINAMT/>
    </BSAMT>
</ENVELOPE>

我的结果应该是:

Opening Stock   Stock-in-Hand-Accesories(KPM)   -15750.01
Opening Stock   Stock-in-Hand-Accesories(KVM)   -16750.01
Closing Stock   Stock-in-Hand-Accesories(KPM)   -54750.01
Closing Stock   Stock-in-Hand-Accesories(KRM)   -74750.01
4

2 回答 2

2

假设唯一的关系是节点的顺序,您可以选择所有BSNAME节点作为锚点,并使用>>and<<运算符找到最近的BSAMTDSPACCNAME节点:

DECLARE @xml XML = '<ENVELOPE>
    <DSPACCNAME>
        <DSPDISPNAME>Opening Stock</DSPDISPNAME>
    </DSPACCNAME>
    <PLAMT>
        <PLSUBAMT/>
        <BSMAINAMT>-44912711.35</BSMAINAMT>
    </PLAMT>
    <BSNAME>
        <DSPACCNAME>
            <DSPDISPNAME>Stock-in-Hand-Accesories(KPM)</DSPDISPNAME>
        </DSPACCNAME>
    </BSNAME>
    <BSAMT>
        <BSSUBAMT>-15750.01</BSSUBAMT>
        <BSMAINAMT/>
    </BSAMT>
    <BSNAME>
        <DSPACCNAME>
            <DSPDISPNAME>Stock-in-Hand-Accesories(KVM)</DSPDISPNAME>
        </DSPACCNAME>
    </BSNAME>
    <BSAMT>
        <BSSUBAMT>-16750.01</BSSUBAMT>
        <BSMAINAMT/>
    </BSAMT>
    <DSPACCNAME>
        <DSPDISPNAME>Closing Stock</DSPDISPNAME>
    </DSPACCNAME>
    <BSNAME>
        <DSPACCNAME>
            <DSPDISPNAME>Stock-in-Hand-Accesories(KPM)</DSPDISPNAME>
        </DSPACCNAME>
    </BSNAME>
    <BSAMT>
        <BSSUBAMT>-54750.01</BSSUBAMT>
        <BSMAINAMT/>
    </BSAMT>
    <BSNAME>
        <DSPACCNAME>
            <DSPDISPNAME>Stock-in-Hand-Accesories(KRM)</DSPDISPNAME>
        </DSPACCNAME>
    </BSNAME>
    <BSAMT>
        <BSSUBAMT>-74750.01</BSSUBAMT>
        <BSMAINAMT/>
    </BSAMT>
</ENVELOPE>';
SELECT refnode.value('(./DSPACCNAME/DSPDISPNAME)[1]', 'VARCHAR(100)') AS [BSNAME]
     , refnode.value('let $c := . return (../BSAMT[. >> $c]/BSSUBAMT)[1]', 'DECIMAL(18,2)') AS [BSAMT]
     , refnode.value('let $c := . return (../DSPACCNAME[. << $c]/DSPDISPNAME)[last()]', 'VARCHAR(100)') AS [DSPACCNAME]
FROM @xml.nodes('//ENVELOPE/BSNAME') x(refnode)

db<>fiddle 上的演示

于 2019-04-23T08:17:20.880 回答
0

虽然按照 Salman A 的建议这样做是可以的,但它很容易出错。看起来这个 XML 是使用自定义 TDL(Tally 插件)形成的。在这种情况下,我同意 Panagiotis Kanavos 的观点,即 XML 格式不正确。您可以让 TDL 开发人员简单地重新排列 XML 标记,方法是在每个父节点的“行”级别和每个子节点的“字段”级别放置一个 XML 标记。请注意,必须使用“重复”变量重复该行,以便在 XML 中出现多个带有子节点的父节点。

您可以参考此参考指南,特别是第 2.2.5 节,了解如何使用 XML 标记。

于 2019-04-29T08:31:05.957 回答