tags:

views:

764

answers:

2

Hi there,

I have a problem where I am attempting to update a set of attributes with a fixed value contained within a repeating section of an XML document using the Microsoft.BizTalk.Streaming.ValueMutator.

For example the XML document which I am attempting to update contains the following input:

<ns0:TestXML xmlns:ns0="http://Test.Schemas"&gt;
   <ns0:NodeA>
      <ns0:NodeB>
         <ns0:alpha Id="1" Value="Apple" Type=""></ns0:alpha>
         <ns0:alpha Id="2" Value="Banana" Type=""></ns0:alpha>
         <ns0:alpha Id="3" Value="Car" Type=""></ns0:alpha>
         <ns0:alpha Id="4" Value="Duck" Type=""></ns0:alpha>
      </ns0:NodeB>
   </ns0:NodeA>
</ns0:TestXML>

The code which I am attempting to use to update the XML document is:

XmlDocument xDocInput = new XmlDocument();
XmlDocument xDocOutput = new XmlDocument();
string inputFileName = @"C:\Input.xml";
string outputFileName = @"C:\Output.xml";
string newValue = "fruit";
string xpathToUpdate = "/*[namespace-uri()='http://Test.Schemas']/*[local-name()='NodeA']/*[local-name()='NodeB']/*[@Type]";

xDocInput.Load(inputFileName);

using (MemoryStream memstream = new MemoryStream())
{

    xDocInput.Save(memstream);
    memstream.Position = 0;

    XPathCollection queries = new XPathCollection();
    queries.Add(new XPathExpression(xpathToUpdate));
    //ValueMutator xpathMatcher = new ValueMutator(this.XPathCallBack);

    //Get resulting stream into response xml
    xDocOutput.Load(new XPathMutatorStream(memstream, queries, delegate(int matchIdx, XPathExpression expr, string origValue, ref string finalValue) { finalValue = newValue; }));
    //System.Diagnostics.Trace.WriteLine("Trace: " + memstream.Length.ToString());
}

xDocOutput.Save(outputFileName);

The resulting output of this code is the file "Output.xml". Contained within the output document "Output.xml" is the following output:

<ns0:TestXML xmlns:ns0="http://Test.Schemas" >
   <ns0:NodeA>
      <ns0:NodeB>
         <ns0:alpha Id="1"  Value="Apple"  Type="" >fruit</ns0:alpha>
         <ns0:alpha Id="2"  Value="Banana"  Type="" >fruit</ns0:alpha>
         <ns0:alpha Id="3"  Value="Child"  Type="" >fruit</ns0:alpha>
         <ns0:alpha Id="4"  Value="Duck"  Type="" >fruit</ns0:alpha>
      </ns0:NodeB>
   </ns0:NodeA>
</ns0:TestXML>

As you will notice the "alpha" element's text value is updated incorrectly. The desired result is to update all attributes named "Type" with the value "Fruit". What is going wrong and how is this problem solved?

A: 

The XPath expression used:

   //namespace-uri()='http://Test.Schemas']/*[local-name()='NodeA']/*[local-name()='NodeB']/*[@Type]

selects only the lements that have a "Type" attribute.

Most probably what is needed is:

   /*[namespace-uri()='http://Test.Schemas']/*[local-name()='NodeA']/*[local-name()='NodeB']/@Type

Hope this helped.

Cheers,

Dimitre Novatchev

Dimitre Novatchev
edited the answer -- asterisks in the XPath expression were not showing, because they were inside a bold (** ... **) field. Please, do try again. – Dimitre Novatchev (0 secs ago)
Dimitre Novatchev
You amended answer results in no changes made to the input document.
chinna
I am not acquainted with BizTalk Server and don't know what the XPathMutatorStream class does. Maybe updates can be performed only on elements? What does the documentation say? If you can send me reference to the docs and a very simple working code sample, I can have a look at it.
Dimitre Novatchev
Sorry, the correct answer was already posted by David Hall. The main difficulty in understanding your question was the *invisible* XPath expression. This is very confusing. Next time do try to format your code!
Dimitre Novatchev
+2  A: 

You need to include the alpha element in your XPath expression.

I ran your code using the expression below:

string xpathToUpdate = "/*[namespace-uri()='http://Test.Schemas']/*[local-name()='NodeA']/*[local-name()='NodeB']/*[local-name()='alpha']/@Type";

and got the following XML

<ns0:TestXML xmlns:ns0="http://Test.Schemas"&gt;
  <ns0:NodeA>
    <ns0:NodeB>
      <ns0:alpha Id="1" Value="Apple" Type="fruit">
      </ns0:alpha>
      <ns0:alpha Id="2" Value="Banana" Type="fruit">
      </ns0:alpha>
      <ns0:alpha Id="3" Value="Car" Type="fruit">
      </ns0:alpha>
      <ns0:alpha Id="4" Value="Duck" Type="fruit">
      </ns0:alpha>
    </ns0:NodeB>
  </ns0:NodeA>
</ns0:TestXML>

Looking at the code you posted, you have probably seen these articles on using the ValueMutator, but just in case there is good info here, here and here.

Heh - Just realised that the last of those is one of my co-workers. Small world.

David Hall
Nice one. Didn't realise it was something so elementary. Thanks for preserving my sanity.
chinna