12

Ben Davis の優れた応答hereに基づいて、XML フラグメントが供給されると、属性の名前と値のペアのリストを返すテーブル値関数を作成しました。それは機能しますが、ルート要素のものだけに制限したい場合、フラグメント全体のすべての属性の名前と値のペアのリストを返します。これどうやってするの?ありがとう、XQuery の初心者から。

INSERT INTO @attributeList
SELECT DISTINCT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(100)),
    attribute.name.value('.','NVARCHAR(MAX)')
FROM @xml.nodes('//@*') attribute(name)

ETA: 実験の結果、セレクター「node()/@*」が機能することが判明しました。助けてくれた人に感謝します。

シンプルなデータ移行アプリケーションまたはデータ ポンプ フロントエンドの Sitecore でこれを使用しています。.NET で POCO オブジェクトを取得して Sitecore に取り込むユーティリティを作成しましたが、現在は移行およびログ データベースを構築しています。ソース オブジェクトは、XML として 1 か所に格納されます。ありがとうございました。

4

1 に答える 1

2

この質問はすでにコメントで回答されているため、これは少し説明を加えた単なる編集です。

実験では、次の XML を使用します。

DECLARE @XML XML =
'<root root_attr="0">
   <leaf leaf_attr="1">one</leaf>
   <brunch brunch_attr="2">
     <leaf leaf_attr="3">three</leaf>
   </brunch>
</root>';

そして、ルート要素の属性のリストを抽出する必要があります: root_attr="0".

XPath リファレンスについては、MSDN XPath 構文ガイドを参照してください。

したがって、「/」はパターンの先頭にある場合は「子」または「ルート ノード」を表し、「@」は「属性」を表し、「*」は「any」と「.」を表します。「現在のコンテキスト」を表します。確かに、これによりすべてのルート属性が得られるはずです。

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/@*') attribute(name);

代わりに、エラーが発生します: Top-level attribute nodes are not supported . XML には、< element >Element Value</element> と <element attribute ="Attribute Value" />の 2 種類のノードがあります。したがって、 XPath は、ルート要素ではなく XML のルートの任意の属性として解釈されます。実際、それは次のように説明できます。/@*

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/') attribute(name);

戻る:

Name Value
---- --------
     onethree

これは、XML ドキュメント全体を表す無名ノードです。'.'XPath でも同じ結果が得られます。

では、XML ドキュメントのルートに任意の要素を指定する必要があります。この式が「再帰的降下」(すべての子) を表していない場合、その構文は「//」(匿名ルート ノードの子 = ルート要素) である必要があります。それはそう

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('//@*') attribute(name);

すべての要素の属性の完全なリストを返します。

Name        Value
----------- --------
root_attr   0
leaf_attr   1
brunch_attr 2
leaf_attr   3

わかりました。ここで、明らかに予約語である「rootelement」の代わりに、XPath で「root」「element」と言う方法が必要です。1 つは「any」を絞り込む方法で、もう 1 つは、ルート要素の実際の名前が不明な場合を除き、「node()」であることを指定する方法です。

指定された XML の場合、これら 3 つは同等です。

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/*/@*') attribute(name);

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/node()/@*') attribute(name);

SELECT
    CAST(attribute.name.query('local-name(.)') AS VARCHAR(MAX)) As [Name],
    attribute.name.value('.','NVARCHAR(MAX)') As [Value]
FROM @XML.nodes('/root/@*') attribute(name);

戻る:

Name      Value
--------- --------
root_attr 0

そこにいます。「//」予約語を回避するための XPath トートロジーのビット。

于 2015-12-24T11:20:21.673 に答える