0

This is my first time using XPath.

This is my XML:

<content type="application/xml">
    <m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
        <d:Guid>YOIYOI-HNON-OIN</d:Guid>
        <d:ObjectId>6000009251</d:ObjectId>
        <d:ProcessType>ZMIN</d:ProcessType>
        <d:ProcessTypeTxt>Incident</d:ProcessTypeTxt>
        <d:Description>Test 2</d:Description>
        <d:IntroText>Incident</d:IntroText>
        <d:CreatedAtDateFormatted>08.05.18</d:CreatedAtDateFormatted>
        <d:ChangedAtDateFormatted>08.05.18</d:ChangedAtDateFormatted>
        <d:PostingDate>2018-05-08T00:00:00</d:PostingDate>
        <d:ChangedAtDate>2018-05-08T00:00:00</d:ChangedAtDate>
        <d:Priority>2</d:Priority>
        <d:PriorityTxt>2: High</d:PriorityTxt>
        <d:PriorityState>None</d:PriorityState>
        <d:Concatstatuser>New</d:Concatstatuser>
        <d:ActionRequired>false</d:ActionRequired>
        <d:StillOpen>true</d:StillOpen>
        <d:Icon></d:Icon>
        <d:SoldToPartyName></d:SoldToPartyName>
        <d:ServiceTeamName></d:ServiceTeamName>
        <d:PersonRespName></d:PersonRespName>
        <d:ConfigItemTxt></d:ConfigItemTxt>
    </m:properties>
</content>

There are other content nodes.

I need to retrieve specific tag values such as:

  • d:Guid
  • d:ProcessType
  • d:Description
  • and so on..

but I don't need all the tag values.

I tried an online Xpath validator where i posted my XML and used this expression:

//content/m:properties/d:Guid | //content/m:properties/d:ObjectId

This gives me the data that I needed but when I use it in c# application it returns null. Can somebody please explain to me why this happens? And if there's any other way to do so besides using XPath?

Here is my c# code :

string xml = System.IO.File.ReadAllText(startupPath);
StringBuilder sb = new StringBuilder();

using (var node = ChoXmlReader.LoadText(xml).WithXPath("//content/m:properties/d:Guid or //content/m:properties/d:ObjectId"))
{
    using (var w = new ChoCSVWriter(sb).WithFirstLineHeader())
    {
        w.Write(node);
    }
}

Console.WriteLine(sb.ToString());
Console.ReadLine();
MarredCheese
  • 17,541
  • 8
  • 92
  • 91
lifeTech
  • 17
  • 6
  • Welcome to Stack Overflow. Please could you provide a [mcve]? We don't know what `ChoXmlReader` or `ChoCSVWriter` are - and the latter doesn't sound like it's relevant to the question. (But no, you don't need to use XPath to query XML. Personally I'd just use straight LINQ to XML.) – Jon Skeet Mar 06 '19 at 20:40
  • Based on your comments it sounds like you want to retrieve multiple nodes from the XML (d:Guid, d:ProcessType, etc) and write them to a CSV. The code you have now won't work, do you have to use `ChoETL`? If not @JonSkeet is correct that you'd be better off using LINQ to XML which has a lot of examples online. – amura.cxg Mar 06 '19 at 21:32

3 Answers3

0

In the online validator you use | but you use or in your code. Does ChoETL really change the way XPaths work? I could not find evidence for that in the documentation.

Also, I think the online tool automatically deduces the namespace prefixes but you need to tell ChoETL the namespaces:

.WithXNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices")

and similar.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • AFAIK, `|` should merge the result set while `or` returns a boolean expression, resulting in `true` if there is a node. If ChoETL changes that behavior, it would be quite surprising. – Thomas Weller Mar 06 '19 at 22:16
  • `using (var node = ChoXmlReader.LoadText(xml) .WithXPath("//content/m:properties/d:Guid | //content/m:properties/d:ObjectId") .WithXmlNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata") .WithXmlNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices")) { using (var w = new ChoCSVWriter(sb).WithFirstLineHeader()) { w.Write(node); } }` This still does not work :s – lifeTech Mar 07 '19 at 10:34
  • @lifeTech: "does not work" is not a very helful statement. What's the error message or result? – Thomas Weller Mar 07 '19 at 12:05
  • there is no error it does not even output the string on the console. – lifeTech Mar 07 '19 at 12:11
  • You definitely need to learn how to use a debugger. Sorry. I can't help. – Thomas Weller Mar 07 '19 at 13:42
0

You can create a Model for this XML file and then serialize that to object and then access the properties you want. Here is the model you can use:

[XmlRoot(ElementName = "properties", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")]
    public class Properties
    {
        [XmlElement(ElementName = "Guid", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string Guid { get; set; }
        [XmlElement(ElementName = "ObjectId", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string ObjectId { get; set; }
        [XmlElement(ElementName = "ProcessType", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string ProcessType { get; set; }
        [XmlElement(ElementName = "ProcessTypeTxt", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string ProcessTypeTxt { get; set; }
        [XmlElement(ElementName = "Description", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string Description { get; set; }
        [XmlElement(ElementName = "IntroText", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string IntroText { get; set; }
        [XmlElement(ElementName = "CreatedAtDateFormatted", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string CreatedAtDateFormatted { get; set; }
        [XmlElement(ElementName = "ChangedAtDateFormatted", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string ChangedAtDateFormatted { get; set; }
        [XmlElement(ElementName = "PostingDate", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string PostingDate { get; set; }
        [XmlElement(ElementName = "ChangedAtDate", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string ChangedAtDate { get; set; }
        [XmlElement(ElementName = "Priority", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string Priority { get; set; }
        [XmlElement(ElementName = "PriorityTxt", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string PriorityTxt { get; set; }
        [XmlElement(ElementName = "PriorityState", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string PriorityState { get; set; }
        [XmlElement(ElementName = "Concatstatuser", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string Concatstatuser { get; set; }
        [XmlElement(ElementName = "ActionRequired", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string ActionRequired { get; set; }
        [XmlElement(ElementName = "StillOpen", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string StillOpen { get; set; }
        [XmlElement(ElementName = "Icon", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string Icon { get; set; }
        [XmlElement(ElementName = "SoldToPartyName", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string SoldToPartyName { get; set; }
        [XmlElement(ElementName = "ServiceTeamName", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string ServiceTeamName { get; set; }
        [XmlElement(ElementName = "PersonRespName", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string PersonRespName { get; set; }
        [XmlElement(ElementName = "ConfigItemTxt", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
        public string ConfigItemTxt { get; set; }
        [XmlAttribute(AttributeName = "m", Namespace = "http://www.w3.org/2000/xmlns/")]
        public string M { get; set; }
        [XmlAttribute(AttributeName = "d", Namespace = "http://www.w3.org/2000/xmlns/")]
        public string D { get; set; }
    }

    [XmlRoot(ElementName = "content")]
    public class Content
    {
        [XmlElement(ElementName = "properties", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")]
        public Properties Properties { get; set; }
        [XmlAttribute(AttributeName = "type")]
        public string Type { get; set; }
    }

and here is the C# code to convert this to object:

XmlSerializer serializer = new XmlSerializer(typeof(Content));
 Content resultingMessage = (Content)serializer.Deserialize(new XmlTextReader(@"XMLFile1.xml"));

and this is the code to access guid property:

string guid = resultingMessage.Properties.Guid;

hope this solve your problem.

PS: I have created model based on your XML file given, if this XML schema changes you need to modify your model accordingly.

Happy coding...

Abhinaw Kaushik
  • 607
  • 6
  • 18
0

Here is how you can output selective xml nodes to csv file using Cinchoo ETL

var nsManager = new XmlNamespaceManager(new NameTable());
//register mapping of prefix to namespace uri 
nsManager.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
nsManager.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");

StringBuilder csv = new StringBuilder();
using (var p = ChoXmlReader.LoadText(xml)
        .WithXPath("//entry/content/m:properties")
        .WithXmlNamespaceManager(nsManager)
        .WithField("Guid", xPath: "d:Guid")
        .WithField("ProcessType", xPath: "d:ProcessType")
        .WithField("Description", xPath: "d:Description")
    )
{
    using (var w = new ChoCSVWriter(csv)
        .WithFirstLineHeader()
        )
        w.Write(p);
}

Console.WriteLine(csv);
Cinchoo
  • 6,088
  • 2
  • 19
  • 34