TSQL 中搜索 xml 查找不存在节点的更好方法

发布于 2024-10-10 01:33:02 字数 1075 浏览 0 评论 0原文

我们有一个源 XML 文件,其中包含一个 address 节点,并且每个节点下面应该有一个 zip_code 节点以便进行验证。我们收到一个未通过架构验证的文件,因为至少有一个节点缺少 zip_code(文件中有数千个地址)。

我们需要找到没有邮政编码的元素,以便我们可以修复文件并向源发送审核报告。

--declare @x xml = bulkcolumn from openrowset(bulk 'x:\file.xml',single_blob) as s
declare @x xml = N'<addresses>
    <address><external_address_id>1</external_address_id><zip_code>53207</zip_code></address>
    <address><external_address_id>2</external_address_id></address>
</addresses>'

declare @t xml = (
select @x.query('for $a in .//address 
    return 
        if ($a/zip_code) 
            then <external_address_id /> 
        else $a/external_address_id')
)
select x.AddressID.value('.', 'int') AddressID
from @t.nodes('./external_address_id') x(AddressID)
where x.AddressID.value('.', 'int') > 0
GO

确实,这是 where 子句让我烦恼。我觉得我依赖于将 null 值强制转换为 0,并且它有效,但我不太确定它应该这样做。我尝试了 .exist 函数的一些变体,但无法获得正确的结果。

We have a source XML file that has an address node, and each node is supposed to have a zip_code node beneath in order to validate. We received a file that failed the schema validation because at least one node was missing it's zip_code (there were several thousand addresses in the file).

We need to find the elements that do not have a zip code, so we can repair the file and send an audit report to the source.

--declare @x xml = bulkcolumn from openrowset(bulk 'x:\file.xml',single_blob) as s
declare @x xml = N'<addresses>
    <address><external_address_id>1</external_address_id><zip_code>53207</zip_code></address>
    <address><external_address_id>2</external_address_id></address>
</addresses>'

declare @t xml = (
select @x.query('for $a in .//address 
    return 
        if ($a/zip_code) 
            then <external_address_id /> 
        else $a/external_address_id')
)
select x.AddressID.value('.', 'int') AddressID
from @t.nodes('./external_address_id') x(AddressID)
where x.AddressID.value('.', 'int') > 0
GO

Really, it's the where clause that bugs me. I feel like I'm depending on a cast for a null value to 0, and it works, but I'm not really sure that it should. I tried a few variations with the .exist function, but I couldn't get the correct result.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

紫南 2024-10-17 01:33:02

如果您只是想确保选择具有 zip_code 元素的 address 元素,则调整您的 XPATH 以在谓词过滤器中包含该条件:

/addresses/address[zip_code]

如果您还想确保 zip_code 元素也有一个值,对 zip_node 使用谓词过滤器来选择那些具有 text() 节点的节点:

/addresses/address[zip_code[text()]]

编辑:

其实我正在寻找
对面的。我需要识别节点
没有拉链,所以我们可以
手动更正源数据。

因此,如果您想识别所有没有 zip_codeaddress 元素,您可以在 XPATH 中指定它,如下所示:

/addresses/address[not(zip_code)]

If you just want to ensure that you are selecting address elements that have a zip_code element, then adjust your XPATH to include that criteria in a predicate filter:

/addresses/address[zip_code]

If you also want to ensure that the zip_code element also has a value, use a predicate filter for the zip_node to select those that have text() nodes:

/addresses/address[zip_code[text()]]

EDIT:

Actually, I'm looking for the
opposite. I need to identify the nodes
that don't have a zip, so we can
manually correct the source data.

So, if you want to identify all of the address elements that do not have a zip_code, you can specify it in the XPATH like this:

/addresses/address[not(zip_code)]
爱的那么颓废 2024-10-17 01:33:02

如果您只想找到那些缺少 元素的节点,您可以使用如下内容:

SELECT
    ADRS.ADR.value('(external_address_id)[1]', 'int') as 'ExtAdrID'
FROM
    @x.nodes('/addresses/address') as ADRS(ADR)
WHERE
    ADRS.ADR.exist('zip_code') = 0

它使用内置的 .exist() 方法在 XQuery 中检查 XML 节点内是否存在子节点。

If you just want to locate those nodes that are missing their <zip_code> element, you could use something like this:

SELECT
    ADRS.ADR.value('(external_address_id)[1]', 'int') as 'ExtAdrID'
FROM
    @x.nodes('/addresses/address') as ADRS(ADR)
WHERE
    ADRS.ADR.exist('zip_code') = 0

It uses the built-in .exist() method in XQuery to check the existence of a subnode inside an XML node.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文