【问题标题】:Remove Element from xDocument based on value in repeating segment根据重复段中的值从 xDocument 中删除元素
【发布时间】:2022-01-06 16:21:50
【问题描述】:

在下面的 XML 中,当任何 /Bundle/entry/resource/Patient/contained/Patient/identifier/system 值属性包含“ remove-this-Patient" ,我可以使用完整值 == "https://example.com/remove-this-Patient" 但“包含”对我来说更好,因为 url 部分可以来自多个地方并且是略有不同。

我已经尝试了下面的两个代码示例和其他变体,但都没有奏效。代码运行没有错误,但没有删除目标 Patient 元素。

正如我尝试在“where”子句中使用 /Bundle/entry/resource/Patient/contained/Patient/id 元素的测试一样,我能够让它工作,所以我认为它有事情要做/Bundle/entry/resource/Patient/contained/Patient/identifier 元素在 Patient 元素内重复。

启动 XML

<Bundle>
    <id value="xxxx" />
    <entry>
    <fullUrl value="xxxxxxx" />
        <resource>
            <Patient>
                <id value="xxxx" />
                <contained>
                    <Practitioner>
                        <id value="xx"/>                        
                    </Practitioner>
                </contained>
                <contained>
                    <Patient>
                        <id value="xxxx" />                     
                        <identifier>
                            <type>
                                <coding>
                                    
                                </coding>
                            </type>
                            <system value="http://example.com/remove-this-Patient" />
                            <value value="xxx" />
                        </identifier>
                        <identifier>
                            <type>
                                <coding>
                                    
                                </coding>
                            </type>
                            <system value="https://example.com/some-other-value" />
                            <value value="xxx" />
                        </identifier>
                    </Patient>
                </contained>
                <contained>
                    <Patient>
                        <id value="xxxx" />                     
                        <identifier>
                            <type>
                                <coding>
                                    
                                </coding>
                            </type>
                            <system value="https://example.com/some-other-thing" />
                            <value value="xxx" />
                        </identifier>
                        <identifier>
                            <type>
                                <coding>
                                    
                                </coding>
                            </type>
                            <system value="https://example.com/some-other-value" />
                            <value value="xxx" />
                        </identifier>
                    </Patient>
                </contained>
            </Patient>
        </resource>     
    </entry>
</Bundle>

当子元素标识符/系统值 = "http://example.com/remove-this-Patient" 时,所需的输出将删除 /contained/Patient 元素

<Bundle>
    <id value="xxxx" />
    <entry>
    <fullUrl value="xxxxxxx" />
        <resource>
            <Patient>
                <id value="xxxx" />
                <contained>
                    <Practitioner>
                        <id value="xx"/>                        
                    </Practitioner>
                </contained>
                <contained>
                    
                </contained>
                <contained>
                    <Patient>
                        <id value="xxxx" />                     
                        <identifier>
                            <type>
                                <coding>
                                    
                                </coding>
                            </type>
                            <system value="https://example.com/some-other-thing" />
                            <value value="xxx" />
                        </identifier>
                        <identifier>
                            <type>
                                <coding>
                                    
                                </coding>
                            </type>
                            <system value="https://example.com/some-other-value" />
                            <value value="xxx" />
                        </identifier>
                    </Patient>
                </contained>
            </Patient>
        </resource>     
    </entry>
</Bundle>

下面的两个查询是我尝试使它与 XDocument 一起使用,但都不起作用。它们运行没有错误,但不会移除患者。

    xdoc.Root.Descendants("entry").Descendants("resource").Descendants("Patient").Descendants("contained").Descendants("Patient").Where(x => x.Element("identifier").Element("system").Attribute("value").Value.Contains("remove-this-Patient")).Remove();
    

    
 xdoc.Root.Descendants("entry").Descendants("resource").Descendants("Patient").Descendants("contained").Descendants("Patient").Where(x => (string)x.Descendants("identifier").Where(y=> ("system").Attribute("value")=="https://example.com/remove-this-Patient").Remove();

【问题讨论】:

  • 这是 XSLT 的完美工作。你愿意吗?
  • 我对 XSLT 不是很熟悉,但我愿意学习
  • 请更新您的问题,并添加所需的输出。
  • c# 中的类对象如果有多个指向对象的链接,则不会被删除。 delete 调用默认的 dispose 方法,该方法检查对象上的链接数,并且仅在没有指向该对象的链接时才调用垃圾收集。删除只是删除对象的一个​​链接。因此,要么有多个指向对象的链接,要么您使用的路径没有找到后代。

标签: c# xml linq


【解决方案1】:

尝试以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication5
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            string id = "xxxx";

            List<XElement> possibleDeletes = doc.Descendants().Where(x => (x.Element("identifier") != null) && (string)x.Element("id").Attribute("value") == id).ToList();

            foreach (XElement possibleDelete in possibleDeletes)
            {
                List<XElement> identifiers = possibleDelete.Elements("identifier").ToList();
                foreach (XElement identifier in identifiers)
                {
                    if (((string)identifier.Element("system").Attribute("value")).Contains("remove")) identifier.Remove(); 
                }
            }
            
        }
    }
 
}

【讨论】:

    【解决方案2】:

    请尝试以下基于 XSLT 转换的解决方案。

    下面的 XSLT 遵循所谓的 Identity Transform 模式。

    第二个模板根据 'remove-this-Patient' 的存在移除不需要的 "/Bundle/entry/resource/Patient/contained/Patient" XML 元素 @value 属性中的 strong> 值。

    输入 XML

    <Bundle>
        <id value="xxxx"/>
        <entry>
            <fullUrl value="xxxxxxx"/>
            <resource>
                <Patient>
                    <id value="xxxx"/>
                    <contained>
                        <Practitioner>
                            <id value="xx"/>
                        </Practitioner>
                    </contained>
                    <contained>
                        <Patient>
                            <id value="xxxx"/>
                            <identifier>
                                <type>
                                    <coding>
                                    </coding>
                                </type>
                                <system value="http://example.com/remove-this-Patient"/>
                                <value value="xxx"/>
                            </identifier>
                            <identifier>
                                <type>
                                    <coding>
                                    </coding>
                                </type>
                                <system value="https://example.com/some-other-value"/>
                                <value value="xxx"/>
                            </identifier>
                        </Patient>
                    </contained>
                    <contained>
                        <Patient>
                            <id value="xxxx"/>
                            <identifier>
                                <type>
                                    <coding>
                                    </coding>
                                </type>
                                <system value="https://example.com/some-other-thing"/>
                                <value value="xxx"/>
                            </identifier>
                            <identifier>
                                <type>
                                    <coding>
                                    </coding>
                                </type>
                                <system value="https://example.com/some-other-value"/>
                                <value value="xxx"/>
                            </identifier>
                        </Patient>
                    </contained>
                </Patient>
            </resource>
        </entry>
    </Bundle>
    

    XSLT

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="/Bundle/entry/resource/Patient/contained/Patient[identifier/system[contains(@value, 'remove-this-Patient')]]">
        </xsl:template>
    </xsl:stylesheet>
    

    输出 XML

    <Bundle>
      <id value="xxxx" />
      <entry>
        <fullUrl value="xxxxxxx" />
        <resource>
          <Patient>
            <id value="xxxx" />
            <contained>
              <Practitioner>
                <id value="xx" />
              </Practitioner>
            </contained>
            <contained />
            <contained>
              <Patient>
                <id value="xxxx" />
                <identifier>
                  <type>
                    <coding />
                  </type>
                  <system value="https://example.com/some-other-thing" />
                  <value value="xxx" />
                </identifier>
                <identifier>
                  <type>
                    <coding />
                  </type>
                  <system value="https://example.com/some-other-value" />
                  <value value="xxx" />
                </identifier>
              </Patient>
            </contained>
          </Patient>
        </resource>
      </entry>
    </Bundle>
    

    【讨论】:

    • 非常感谢您提供这个。我正在实施您的建议。一旦我得到它的工作,我会把它标记为答案。
    • 效果很好,谢谢。
    • @David,很高兴听到建议的解决方案对您有用。它只是 XSLT 中的一个行模板!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    相关资源
    最近更新 更多