简体   繁体   English

MS SQL URL 编码 XML 读取子节点

[英]MS SQL URL Encoded XML Reading Child Node

i need some help for reading the value of a node xml in ms sql.我需要一些帮助来读取 ms sql 中节点 xml 的值。

The table looks like桌子看起来像

SQL Table SQL表

the settings column has the datatype "xml"设置列的数据类型为“xml”

i want to read out some information with an sql query inside the xml column.我想用 xml 列中的 sql 查询读出一些信息。

The problem is the format inside the xml see here:问题是 xml 内部的格式,请参见此处:

<FCProfile version="5.1.0.1" fpid="142" fid="5" guid="e24fb72b-fc8f-435b-8b33-562a018d64e5" name="Vertrieb-IF FCO" type="Custom" useIndexFilter="true" fGuid="2ce5d088-509d-4bef-acc2-5d1dd79607a7">
  <IndexFilters>
    <SearchFilter format="Extended" operation="And">
      <ExtendedStatement>&lt;?xml version="1.0"?&gt;
&lt;QueryBuilderSettings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://dev.docuware.com/settings/web/querybuilder"&gt;
  &lt;Root&gt;
    &lt;Operation&gt;And&lt;/Operation&gt;
    &lt;Conditions xsi:type="Condition"&gt;
      &lt;DBName&gt;ARCHIV&lt;/DBName&gt;
      &lt;Provider xsi:type="TextConditionProvider"&gt;
        &lt;Operation&gt;Equal&lt;/Operation&gt;
        &lt;Value&gt;Vertrieb&lt;/Value&gt;
        &lt;SystemFunction&gt;None&lt;/SystemFunction&gt;
      &lt;/Provider&gt;
    &lt;/Conditions&gt;
    &lt;Conditions xsi:type="GroupCondition"&gt;
      &lt;Operation&gt;Or&lt;/Operation&gt;
      &lt;Conditions xsi:type="Condition"&gt;
        &lt;DBName&gt;DOKUMENTART&lt;/DBName&gt;
        &lt;Provider xsi:type="TextConditionProvider"&gt;
          &lt;Operation&gt;Equal&lt;/Operation&gt;
          &lt;Value&gt;Baukasse&lt;/Value&gt;
          &lt;SystemFunction&gt;None&lt;/SystemFunction&gt;
        &lt;/Provider&gt;
      &lt;/Conditions&gt;
      &lt;Conditions xsi:type="Condition"&gt;
        &lt;DBName&gt;DOKUMENTART&lt;/DBName&gt;
        &lt;Provider xsi:type="TextConditionProvider"&gt;
          &lt;Operation&gt;Equal&lt;/Operation&gt;
          &lt;Value&gt;Anzahlungsrechnung (ausgehend)&lt;/Value&gt;
          &lt;SystemFunction&gt;None&lt;/SystemFunction&gt;
        &lt;/Provider&gt;
      &lt;/Conditions&gt;
      &lt;Conditions xsi:type="Condition"&gt;
        &lt;DBName&gt;DOKUMENTART&lt;/DBName&gt;
        &lt;Provider xsi:type="TextConditionProvider"&gt;
          &lt;Operation&gt;Equal&lt;/Operation&gt;
          &lt;Value&gt;Sonderrechnung&lt;/Value&gt;
          &lt;SystemFunction&gt;None&lt;/SystemFunction&gt;
        &lt;/Provider&gt;
      &lt;/Conditions&gt;
    &lt;/Conditions&gt;
  &lt;/Root&gt;
&lt;/QueryBuilderSettings&gt;</ExtendedStatement>
    </SearchFilter>
  </IndexFilters>
  <GeneralRights>General_Search, General_DisplayDocument, General_Export</GeneralRights>
  <AnnotationRights>Annotation_New</AnnotationRights>
  <FieldRights>
    <FieldRight right="Field_Modify" />
    <FieldRight right="Field_Read">
      <Fields>,KUNDE,AUFTRAG,MASCHINEN,DOKUMENTART,DOKUMENTDATUM,BETREFF,BEREICH,VORGANG,STATUS,DATEINAME,GESELLSCHAFT,HANDELSPARTNER,HANDELSPARTNERNR,PROJEKT,DOKUMENT_NR,ENDKUNDE,NAME_KONTAKT,BETRAG,ABTEILUNG,VERTRETER,ZEITRAUM_VON,ZEITRAUM_BIS,ARCHIV,ABGELEGT_VON,</Fields>
    </FieldRight>
    <FieldRight right="Field_Search">
      <Fields>,KUNDE,AUFTRAG,MASCHINEN,DOKUMENTART,DOKUMENTDATUM,BETREFF,BEREICH,VORGANG,STATUS,DATEINAME,GESELLSCHAFT,HANDELSPARTNER,HANDELSPARTNERNR,PROJEKT,DOKUMENT_NR,ENDKUNDE,NAME_KONTAKT,BETRAG,ABTEILUNG,VERTRETER,ZEITRAUM_VON,ZEITRAUM_BIS,ARCHIV,ABGELEGT_VON,</Fields>
    </FieldRight>
    <FieldRight right="Field_Write" />
  </FieldRights>
</FCProfile>

Some Parts are enclosed with "<" and ">" and some with "& lt;"有些部分用“<”和“>”括起来,有些用“& lt;”括起来and "& gt;"和“&gt;”

The script i tried is:我试过的脚本是:

select X.Y.value('(ExtendedStatement)[1]', 'VARCHAR(4000)') as SettingsText
from [dwsystem].[dbo].[DWFCProfile] e
OUTER APPLY e.settings.nodes('FCProfile/IndexFilters/SearchFilter') as X(Y)
where fid=5

but i want to read out only the "Value" in the"& lt;"但我只想读出“&lt;”中的“价值” Value "& gt;"值“>” Part Like: Vertrieb, or Baukasse, or Anzahlungsrechnung部分喜欢:Vertrieb,或 Baukasse,或 Anzahlungsrechnung

if i try something like this:如果我尝试这样的事情:

select X.Y.value('(Value)[1]', 'VARCHAR(4000)') as SettingsText
from [dwsystem].[dbo].[DWFCProfile] e
OUTER APPLY e.settings.nodes('FCProfile/IndexFilters/SearchFilter/ExtendedStatement') as X(Y)
where fid=5

I get a "NULL" Value.我得到一个“NULL”值。

I also tried this:我也试过这个:

select cast(settings.value('(ExtendedStatement)[1]', 'varchar(max)') as xml).value('(FCProfile/IndexFilters/SearchFilter/ExtendedStatement/value)[1]', 'varchar(max)') as Text
 FROM [dwsystem].[dbo].[DWFCProfile]
  where fid=5

I also get a "NULL" Value.我也得到一个“NULL”值。

I found one interesting blog with my problem:我发现了一个有趣的博客来解决我的问题:

https://mcguirev10.com/2018/12/16/query-plaintext-or-encoded-xml-with-sql-server.html https://mcguirev10.com/2018/12/16/query-plaintext-or-encoded-xml-with-sql-server.html

but i can not get the solution.但我无法得到解决方案。

Here you can see data from my database:在这里你可以看到我的数据库中的数据:

data数据

Would be great if someone could help me:)如果有人可以帮助我会很棒:)

//Edit //编辑

Now i tried the answer: (Modified it by Column operation)现在我尝试了答案:(通过列操作修改它)

with xmlnamespaces (
  'http://dev.docuware.com/settings/web/querybuilder' as qb
)
select
  a.name as Benutzer,
  c.name as Gruppe,
  e.name as Rolle,
  i.name as Archivprofile,
  k.name as Archiv,
  Provider.value('(qb:Value/text())[1]', 'nvarchar(max)') as Value,
Provider.value('(qb:Operation/text())[1]', 'nvarchar(max)') as Operation
from dbo.DWUser as a
left join dbo.DWUserToGroup b on b.uid=a.uid
left join dbo.DWGroup c on c.gid=b.gid
left join dbo.DWUserToRole d on d.uid=a.uid
left join dbo.DWGroupToRole j on j.gid=c.gid
left join dbo.DWRoles e on e.rid=j.rid
left join dbo.DWFCProfileToRole h on h.rid=e.rid
left join dbo.DWFCProfile i on i.fpid=h.fpid
left join dbo.DWFileCabinet k on k.fid=i.fid
outer apply i.settings.nodes('/FCProfile/IndexFilters/SearchFilter/ExtendedStatement') SearchFilter(ExtendedStatement)
outer apply (
  select cast(ExtendedStatement.value('(./text())[1]', 'nvarchar(max)') as xml) as EmbeddedXML
) Embedded
outer apply EmbeddedXML.nodes('/qb:QueryBuilderSettings/qb:Root/qb:Conditions/qb:Provider') as Conditions(Provider)
order by k.name;

this solution gives back only the first input value of the XML Node "Value"此解决方案仅返回 XML 节点“值”的第一个输入值

Is it possible to get all inputs of "Value" from the data?是否可以从数据中获取“值”的所有输入?

Like here in the XML you have fpid = 142 and fid = 5, there are 4 values of "value" (Vertrieb, Baukasse, Anzahlungsrechnung and Sonderrechnung).就像在 XML 中一样,您有 fpid = 142 和 fid = 5,“值”有 4 个值(Vertrieb、Baukasse、Anzahlungsrechnung 和 Sonderrechnung)。


 & lt;Value& gt;Vertrieb& lt;/Value& gt;
 & lt;Value& gt;Baukasse& lt;/Value& gt;
 & lt;Value& gt;Anzahlungsrechnung (ausgehend)& lt;/Value& gt;
 & lt;Value& gt;Sonderrechnung & lt;/Value& gt;

Here is a screenshot of the Database这是数据库的屏幕截图数据库

In the example the select schould give在示例中 select 应该给出

4 times fpid = 142 and fid = 5 with value like(see above) maybe in the xml column settings of fpid = 26 and fid = 5 there are 2 values in "value" in fpid = 177 and fid = 5 there is only one value in "value" in the xml column 4 次 fpid = 142 和 fid = 5 的值(见上文)可能在 fpid = 26 和 fid = 5 的 xml 列设置中,在 fpid = 177 和 fid = 5 中的“值”中有 2 个值,fid = 5 只有一个xml 列中“值”中的值

and so on.等等。

Even though the question is already 1 year and 5 months old, I would like to share my findings.即使这个问题已经 1 年零 5 个月了,我还是想分享我的发现。 The difficulty is that the DBNAME nodes can be at different levels.困难在于DBNAME节点可以处于不同的级别。 I took the approach of looking for them in the EXTENDED STATEMENT regardless of their level and then fetching the then associated information such as OPERATION and VALUE in addition in a recursive manner.我采取了在EXTENDED STATEMENT中查找它们的方法,而不管它们的级别如何,然后以递归方式另外获取当时相关的信息,例如OPERATIONVALUE

Additionally one must consider the NAMESPACES with the EXTENDED STATEMENT .此外,必须考虑带有NAMESPACES EXTENDED STATEMENT的命名空间。 Here I used the Asterisk (example: *:Operation ) parameter, because I saw no other possibility than to circumvent the namespaces with this.在这里,我使用了 Asterisk (example: *:Operation ) 参数,因为除了用它来规避命名空间外,我没有看到其他可能性。 But then also WITH XMLNAMESPACES (...) is not really necessary - therefore i have commented it in the code.但是WITH XMLNAMESPACES (...)也不是真正必要的——因此我在代码中对其进行了注释。

(It is important to know that IF you use the XMLNAMESPACES, that you DON'T forget any namespace.). (重要的是要知道,如果您使用 XMLNAMESPACES,则不要忘记任何命名空间。)。

Interestingly, I was looking for this solution myself for this "Docuware specific" problem and therefore ended up exactly with your question.有趣的是,我自己正在为这个“Docuware 特定”问题寻找这个解决方案,因此最终得到了你的问题。

    --with xmlnamespaces (
    --  'http://www.w3.org/2001/XMLSchema' as xsd,
    --  'http://www.w3.org/2001/XMLSchema-instance' as xsi,
    --  'http://dev.docuware.com/settings/web/querybuilder' as qb
    --)
    select A.fpid as PROFILE_ID
    ,A.fid as FILECABINET_ID
    ,A.name as PROFILE_NAME
    ,cast(ExtendedStatement.value('(./text())[1]', 'nvarchar(max)') as xml) as ESXML
    ,x.y.value('(../../@*:type)[1]', 'nvarchar(max)') as Conditions_type
    ,x.y.value('(../../*:Operation)[1]', 'nvarchar(max)') as Conditions_Operation
    ,x.y.value('(text())[1]', 'nvarchar(max)') as DBName
    ,x.y.value('(../*:Provider/*:Operation)[1]', 'nvarchar(max)') as Provider_Operation
    ,x.y.value('(../*:Provider/*:Value)[1]', 'nvarchar(max)') as Provider_Value
    ,x.y.value('(../*:Provider/*:AddWildcard)[1]', 'nvarchar(max)') as Provider_AddWildcard
    ,x.y.value('(../*:Provider/*:SystemFunction)[1]', 'nvarchar(max)') as Provider_SystemFunction
    ,x.y.value('(../*:Provider/@*:type)[1]', 'nvarchar(max)') as Provider_Type
    FROM [dwsystem].[dbo].[DWFCProfile] A
    OUTER APPLY A.settings.nodes('/FCProfile/IndexFilters/SearchFilter/ExtendedStatement') as SearchFilter(ExtendedStatement)
    outer apply (
    select cast(ExtendedStatement.value('(./text())[1]', 'nvarchar(max)') as xml) as EmbeddedXML
    ) Embedded
    outer apply EmbeddedXML.nodes('//*:DBName') as x(y)
    where A.type = 'DocuWare.Settings.FCProfiles.FCProfile, DocuWare.Settings'

Example Result示例结果示例结果

Well, you seem to have two problems here:好吧,您似乎在这里遇到了两个问题:

  1. Embedded XML, and嵌入式 XML 和
  2. Embedded XML with namespaces.带有命名空间的嵌入式 XML。

The elements you're trying to query in the embedded have a default namespace defined on the QueryBuilder element of http://dev.docuware.com/settings/web/querybuilder , so you'll need to reference that in your XPath query...您尝试在嵌入式中查询的元素具有在http://dev.docuware.com/settings/web/querybuilderQueryBuilder元素上定义的默认命名空间,因此您需要在 XPath 查询中引用它。 ..

with xmlnamespaces (
  'http://dev.docuware.com/settings/web/querybuilder' as qb
)
select Provider.value('(qb:Value/text())[1]', 'nvarchar(max)') as Value
from (
  select cast(ExtendedStatement.value('(./text())[1]', 'nvarchar(max)') as xml) as EmbeddedXML
  from dbo.DWFCProfile
  cross apply settings.nodes('/FCProfile/IndexFilters/SearchFilter/ExtendedStatement') SearchFilter(ExtendedStatement)
  where fid = 5
) Embedded
cross apply EmbeddedXML.nodes('/qb:QueryBuilderSettings/qb:Root/qb:Conditions/qb:Provider') as Conditions(Provider);

Because there are so many left join s involved in your extended query you can use outer apply instead of cross apply to allow rows to be returned even if some values might be null.因为在您的扩展查询中涉及到如此多的left join ,您可以使用outer apply而不是cross apply来允许返回行,即使某些值可能是 null。 So that looks like the following (untested, because I don't have your database available)...所以看起来如下(未经测试,因为我没有你的数据库可用)......

with xmlnamespaces (
  'http://dev.docuware.com/settings/web/querybuilder' as qb
)
select
  a.name as Benutzer,
  c.name as Gruppe,
  e.name as Rolle,
  i.name as Archivprofile,
  k.name as Archiv,
  Provider.value('(qb:Value/text())[1]', 'nvarchar(max)') as Value
from dbo.DWUser as a
left join dbo.DWUserToGroup b on b.uid=a.uid
left join dbo.DWGroup c on c.gid=b.gid
left join dbo.DWUserToRole d on d.uid=a.uid
left join dbo.DWGroupToRole j on j.gid=c.gid
left join dbo.DWRoles e on e.rid=j.rid
left join dbo.DWFCProfileToRole h on h.rid=e.rid
left join dbo.DWFCProfile i on i.fpid=h.fpid
left join dbo.DWFileCabinet k on k.fid=i.fid
outer apply i.settings.nodes('/FCProfile/IndexFilters/SearchFilter/ExtendedStatement') SearchFilter(ExtendedStatement)
outer apply (
  select cast(ExtendedStatement.value('(./text())[1]', 'nvarchar(max)') as xml) as EmbeddedXML
) Embedded
outer apply EmbeddedXML.nodes('/qb:QueryBuilderSettings/qb:Root/qb:Conditions/qb:Provider') as Conditions(Provider)
order by k.name;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM