Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new functions: replace and poke for inner xml #970

Merged
merged 2 commits into from
Oct 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/app/FakeLib/XMLHelper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ let XPathReplace xpath value (doc : XmlDocument) =
node.Value <- value
doc

/// Replaces the inner text of an xml node in the XML document specified by a XPath expression.
let XPathReplaceInnerText xpath innerTextValue (doc : XmlDocument) =
let node = doc.SelectSingleNode xpath
if node = null then failwithf "XML node '%s' not found" xpath
else
node.InnerText <- innerTextValue
doc

/// Selects a xml node value via XPath from the given document
let XPathValue xpath (namespaces : #seq<string * string>) (doc : XmlDocument) =
let nsmgr = XmlNamespaceManager(doc.NameTable)
Expand All @@ -132,6 +140,12 @@ let XmlPoke (fileName : string) xpath value =
doc.Load fileName
XPathReplace xpath value doc |> fun x -> x.Save fileName

/// Replaces the inner text of an xml node in a XML file at the location specified by a XPath expression.
let XmlPokeInnerText (fileName : string) xpath innerTextValue =
let doc = new XmlDocument()
doc.Load fileName
XPathReplaceInnerText xpath innerTextValue doc |> fun x -> x.Save fileName

/// Replaces text in a XML document specified by a XPath expression, with support for namespaces.
let XPathReplaceNS xpath value (namespaces : #seq<string * string>) (doc : XmlDocument) =
let nsmgr = XmlNamespaceManager(doc.NameTable)
Expand All @@ -142,12 +156,28 @@ let XPathReplaceNS xpath value (namespaces : #seq<string * string>) (doc : XmlDo
node.Value <- value
doc

/// Replaces inner text in a XML document specified by a XPath expression, with support for namespaces.
let XPathReplaceInnerTextNS xpath innerTextValue (namespaces : #seq<string * string>) (doc : XmlDocument) =
let nsmgr = XmlNamespaceManager(doc.NameTable)
namespaces |> Seq.iter nsmgr.AddNamespace
let node = doc.SelectSingleNode(xpath, nsmgr)
if node = null then failwithf "XML node '%s' not found" xpath
else
node.InnerText <- innerTextValue
doc

/// Replaces text in a XML file at the location specified by a XPath expression, with support for namespaces.
let XmlPokeNS (fileName : string) namespaces xpath value =
let doc = new XmlDocument()
doc.Load fileName
XPathReplaceNS xpath value namespaces doc |> fun x -> x.Save fileName

/// Replaces inner text of an xml node in a XML file at the location specified by a XPath expression, with support for namespaces.
let XmlPokeInnerTextNS (fileName : string) namespaces xpath innerTextValue =
let doc = new XmlDocument()
doc.Load fileName
XPathReplaceInnerTextNS xpath innerTextValue namespaces doc |> fun x -> x.Save fileName

/// Loads the given text into a XslCompiledTransform.
let XslTransformer text =
if isNullOrEmpty text then null
Expand Down
80 changes: 77 additions & 3 deletions src/test/Test.FAKECore/XmlSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,42 @@ public class when_poking_xml
.ShouldEqual(TargetText.Replace("\r", "").Replace("\n", ""));
}

public class when_poking_xml_innertext
{
const string OriginalText =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<painting>" +
" <img src=\"madonna.jpg\" alt=\"Foligno Madonna, by Raphael\" />" +
" <caption>This is Raphael's \"Foligno\" Madonna, painted in <date year=\"1511\" /> - <date year=\"1512\" />.</caption>" +
" <note name=\"Type\">Oil on wood, transferred to canvas</note>" +
" <note name=\"Dimensions\">320 cm × 194 cm (130 in × 76 in)</note>" +
" <note name=\"Location\">Pinacoteca Vaticana, Vatican City</note>" +
"</painting>";

const string XPath = "painting/note[@name='Location']";

static readonly string FileName = Path.Combine(TestData.TestDir, "test.xml");

static XmlDocument _doc;
static readonly string TargetText = OriginalText.Replace("Pinacoteca Vaticana, Vatican City", "Vatican City");


Cleanup after = () => FileHelper.DeleteFile(FileName);

Establish context = () =>
{
StringHelper.WriteStringToFile(false, FileName, OriginalText);
_doc = new XmlDocument();
_doc.LoadXml(OriginalText);
};

Because of = () => XMLHelper.XmlPokeInnerText(FileName, XPath, "Vatican City");

It should_equal_the_target_text =
() => StringHelper.ReadFileAsString(FileName).Replace("\r", "").Replace("\n", "")
.ShouldEqual(TargetText.Replace("\r", "").Replace("\n", ""));
}

public class when_modifying_xml_with_xpath
{
const string OriginalText =
Expand Down Expand Up @@ -85,8 +121,6 @@ public class when_modifying_xml_with_xpath
() => _resultDoc.OuterXml.ShouldEqual(_targetText);
}



public class when_poking_xml_and_ns
{
const string OriginalText =
Expand Down Expand Up @@ -126,7 +160,47 @@ public class when_poking_xml_and_ns
() => StringHelper.ReadFileAsString(FileName).Replace("\r", "").Replace("\n", "").Replace("'", "\"")
.ShouldEqual(TargetText.Replace("\r", "").Replace("\n", "").Replace("'", "\""));
}


public class when_poking_xml_innertext_and_ns
{
const string OriginalText =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<asmv1:assembly manifestVersion='1.0' xmlns='urn:schemas-microsoft-com:asm.v1' xmlns:asmv1='urn:schemas-microsoft-com:asm.v1' xmlns:asmv2='urn:schemas-microsoft-com:asm.v2' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
" <assemblyIdentity version='0.1.0.0' name='MyApplication' />" +
" <assemblyDescription></assemblyDescription>" +
"</asmv1:assembly>";

const string XPath = "//asmv1:assembly/asmv1:assemblyDescription";

static readonly string FileName = Path.Combine(TestData.TestDir, "test.xml");

static XmlDocument _doc;
static readonly string TargetText = OriginalText.Replace("<assemblyDescription></assemblyDescription>", "<assemblyDescription>A really great assembly. Really.</assemblyDescription>");
static List<Tuple<string, string>> _nsdecl;


Cleanup after = () => FileHelper.DeleteFile(FileName);

Establish context = () =>
{
StringHelper.WriteStringToFile(false, FileName, OriginalText);
_doc = new XmlDocument();
_doc.LoadXml(OriginalText);
_nsdecl = new List<Tuple<string, string>>
{
new Tuple<string, string>("", "urn:schemas-microsoft-com:asm.v1"),
new Tuple<string, string>("asmv1", "urn:schemas-microsoft-com:asm.v1"),
new Tuple<string, string>("asmv2", "urn:schemas-microsoft-com:asm.v2"),
new Tuple<string, string>("xsi", "http://www.w3.org/2001/XMLSchema-instance")
};
};

Because of = () => XMLHelper.XmlPokeInnerTextNS(FileName, _nsdecl, XPath, "A really great assembly. Really.");

It should_equal_the_target_text =
() => StringHelper.ReadFileAsString(FileName).Replace("\r", "").Replace("\n", "").Replace("'", "\"")
.ShouldEqual(TargetText.Replace("\r", "").Replace("\n", "").Replace("'", "\""));
}

public class when_modifying_xml_with_xpath_and_ns
{
Expand Down