DaveN59
DaveN59

Reputation: 3718

How can I remove an unwanted node from a list of XElements?

I need to use C# to manicure the response from a service before handing it off to the caller. The service takes a series of requests in XML format, formats the message and send it to the service. The response looks similar to this:

<SvcRes>
    <SvcVer>1.0</SvcVer>
    <MsgUUID>12345678-1234-1234-1234-123456789012</MsgUUID>
    <Svc>
        <SvcParms>
            <ApplID>App</ApplID>
            <SvcID>AppSrch</SvcID>
            <SvcVer>1.0</SvcVer>
        </SvcParms>
        <MsgData>
            <AppResData>
                <Key>xxxxxxxx</Key>
                <Rslt>xxxxxxxx</Rslt>
                <ErrCde>0</ErrCde>
                <ApplMsgLst>
                    <ApplMsg>
                        <ApplMsgApplId>D6</ApplMsgApplId>
                        <ApplMsgNbr>0</ApplMsgNbr>
                        <ApplMsgTxt>INQUIRY COMPLETE     09:23:53</ApplMsgTxt>
                        <ApplMsgErrInd>N</ApplMsgErrInd>
                    </ApplMsg>
                </ApplMsgLst>
            </AppResData>
        </MsgData>
        <ErrCde>0</ErrCde>
        <ErrMsg/>
    </Svc>
    <Svc>
        <SvcParms>
            <ApplID>DP</ApplID>
            <SvcID>DPKywrd</SvcID>
            <SvcVer>1.0</SvcVer>
            <RqstUUID>12345678-1234-1234-1234-123456789012</RqstUUID>
        </SvcParms>
        <MsgData>
            <AppResData>
                <Key>xxxxxxxx</Key>
                <Rslt>xxxxxxxx</Rslt>
                <ErrCde>0</ErrCde>
                <ApplMsgLst>
                    <ApplMsg>
                        <ApplMsgApplId>D6</ApplMsgApplId>
                        <ApplMsgNbr>0</ApplMsgNbr>
                        <ApplMsgTxt>INQUIRY COMPLETE     09:23:53</ApplMsgTxt>
                        <ApplMsgErrInd>N</ApplMsgErrInd>
                    </ApplMsg>
                </ApplMsgLst>
            </AppResData>
        </MsgData>
        <ErrCde>0</ErrCde>
        <ErrMsg/>
      <Svc>
    <ErrCde>0</ErrCde>
    <ErrMsg>Success</ErrMsg>
</SvcRes>

I need to pull out the AppResData nodes, then strip out the ApplMsgLst nodes from each of them before sending the results back to the caller. The resulting XML should be like this:

<AppResData>
    <Key>xxxxxxxx</Key>
    <Rslt>xxxxxxxx</Rslt>
    <ErrCde>0</ErrCde>
</AppResData>
<AppResData>
    <Key>xxxxxxxx</Key>
    <Rslt>xxxxxxxx</Rslt>
    <ErrCde>0</ErrCde>
</AppResData>

I can get a list of XElement nodes using the following 2 lines of code:

var xml = XElement.Parse(xmlResponse);
var msgData = xml.DescendantsAndSelf("MsgData");

Is there another way to do this? There is no file, this is all string data in a SOAP web service.

Upvotes: 0

Views: 73

Answers (2)

Cinchoo
Cinchoo

Reputation: 6322

You can try this with Cinchoo ETL - an open source library to do this transformation easily

StringBuilder xml = new StringBuilder();

using (var r = ChoXmlReader.LoadText("*** YOUR XML CONTENTS ***")
    .WithXPath("//AppResData")
    .WithField("Key")
    .WithField("Rslt")
    .WithField("ErrCde")
    )
{
    using (var w = new ChoXmlWriter(xml)
        )
    {
        w.Write(r);
    }
}
Console.WriteLine(xml.ToString());

Output:

<Root>
  <AppResData>
    <Key>xxxxxxxx</Key>
    <Rslt>xxxxxxxx</Rslt>
    <ErrCde>0</ErrCde>
  </AppResData>
  <AppResData>
    <Key>xxxxxxxx</Key>
    <Rslt>xxxxxxxx</Rslt>
    <ErrCde>0</ErrCde>
  </AppResData>
</Root>

Upvotes: 0

Yitzhak Khabinsky
Yitzhak Khabinsky

Reputation: 22157

Here is an XSLT based solution.

Parameters:

  • Input XML as a string data type.
  • XSLT as a file.
  • Output XML as a string data type.

XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="/SvcRes">
        <root>
            <xsl:for-each select="Svc/MsgData/AppResData">
                <xsl:copy>
                    <xsl:copy-of select="Key"/>
                    <xsl:copy-of select="Rslt"/>
                    <xsl:copy-of select="ErrCde"/>
                </xsl:copy>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:stylesheet>

c#

void Main()
{
    const string XSLTFILE = @"e:\Temp\DaveN59.xslt";
    string inputXML = @"<SvcRes>
        ...
    </SvcRes>";

    try
    {
        StringReader rdr = new StringReader(inputXML);
        XPathDocument XPathDoc = new XPathDocument(rdr);

        XslCompiledTransform xslt = new XslCompiledTransform();
        xslt.Load(XSLTFILE);

        StringWriter sw = new StringWriter();
        using (XmlWriter xwo = XmlWriter.Create(sw, xslt.OutputSettings))
        {
            xslt.Transform(XPathDoc, xwo);
        }
        
        Console.WriteLine(sw.ToString());
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

Output XML

<root>
  <AppResData>
    <Key>xxxxxxxx</Key>
    <Rslt>xxxxxxxx</Rslt>
    <ErrCde>0</ErrCde>
  </AppResData>
  <AppResData>
    <Key>xxxxxxxx</Key>
    <Rslt>xxxxxxxx</Rslt>
    <ErrCde>0</ErrCde>
  </AppResData>
</root>

Upvotes: 1

Related Questions