using linq2Xml to edit element but with Xpath? - xpath

Im loading an xml from stream
XDocument xmlFile = XDocument.Load(stream);
var query = from c in xmlFile.Elements("//Band") //error here
select c;
modify query....
Is it possible to find elements which are in format of Xpath ? (//Band) ?
p.s. I can use descendants but I want to ask about xpath....

Use the Descendants() method:
from c in xmlFile.Descendants("Band")
select c;
Or if you want to specify true XPath expressions, use the following Extensions:
XPathEvaluate()
XPathSelectElement()
XPathSelectElements()

Related

How to apply predicate to GPath when I am using XMLSlurper

lets say I have the following XML
<InvoiceLines>
<InvoiceLine>
<InsertionDate>29.01.2015</InsertionDate>
<Productnbr>0102</Productnbr>
</InvoiceLine>
<InvoiceLine>
<InsertionDate>29.02.2015</InsertionDate>
<Productnbr>0103</Productnbr>
</InvoiceLine>
</InvoiceLines>
and I would like to get the insertion date of InvoiceLine that has Productnbr = 0103. If I would write xpath I would write somthing like:
//InvoiceLine[./Productnbr='0103']/InsertionDate
but I would like to use GPath since I am using XMLSlurper in my code. Is there a way how to apply predicate to GPath? Thank you
You can use a tree search with find and then get the value of it's child:
def date = new XmlSlurper().parseText(xml)
.'**'
.find { it.Productnbr == '0103' }?.InsertionDate

Parsing xml with Go, ignoring nested elements?

I am trying to parse a html document with the Golang xml parser. I have managed it to extract all the <li>elements but if the element contains a link <a>, then the content of the link is ignored. I would like to just ignore the nested <a> and display it's content as plain text but I don't know how.
Here is my code:
d := xml.NewDecoder(resp.Body)
d.Strict = false
d.AutoClose = xml.HTMLAutoClose
d.Entity = xml.HTMLEntity
type list_item struct {
Data string `xml:",chardata"`
}
for {
t,_ := d.Token()
if t == nil {
break
}
switch se := t.(type) {
case xml.StartElement:
if se.Name.Local == "li" {
var q list_item
d.DecodeElement(&q, &se)
c.Infof("%+v\n", q)
}
}
}
Is there any way to just ignore nested elements and display their content?
Constder using specialized package for parsing HTML. In general, HTML is not XML (XHTML 1.0 is, but documents formatted using it are not very common, and that standard has been deprecated).
An even better approach in my opinion—given your apparent use case,— would be using XPath to extract the necessary information using a query.
As to the question as stated, I think there's no built-in way to do what you want: the xml.Decoder implements the Skip() method but it only allows you to skip over unneeded content; there's nothing returning "inner XML" as is. You could roll this yourself by using xml.Decoder's RawToken(): by immediately rendering whatever it returns until it returns something denoting and end element you're looking for (you'll have to implement support for handling nested elements).
I found a library that uses the jQuery style of getting html information: http://godoc.org/github.com/PuerkitoBio/goquery
I used that and it solved the problem.

Linq to XML + chaining expressions

I have the following code that's repeated:
var ccaNumber = (from r in xDoc.Elements("ResultSet").Elements("DataRow")
where Convert.ToInt32(r.Element("PaymentPlanNumber").Value) == payPlan.OrderNumber
Ideally, I want to create the above as an expression then add my clause to the end of it.
So, I created the expression as follows:
Expression currExp = from r in xDoc.Elements("ResultSet").Elements("DataRow")
where Convert.ToInt32(r.Element("PaymentPlanNumber").Value) == payPlan.OrderNumber;
I now want to combine them:
var ccaNumber = (currExp select r.Element("CreditCardAuthorityNumber").Value).FirstOrDefault();
However I now get the following error:
Invalid expression term ')'
Any suggestions?
ta,
yogi
I think you are mixing things up here.
What you can do is:
var items = from r in xDoc.Elements("ResultSet").Elements("DataRow")
where Convert.ToInt32(r.Element("PaymentPlanNumber").Value) == payPlan.OrderNumber
select r;
This declares items as a Enumerable of elements that match your Where-Condition.
And then you can use those defined items like this:
var ccaNumber = items.Select(item=>item.Element("CreditCardAuthorityNumber").Value).FirstOrDefault();
However, this is all utilising lazy evaluation and you need to take care of multiple enumerations here. Here is a pretty indepth explanaition that is way better than my sh*tty english.
When adding to an existing expression, you need to use the lambda syntax, not the Linq syntax:.
Try:
var ccaNumber = (currExp
.Select(r=>r.Element("CreditCardAuthorityNumber").Value))
.FirstOrDefault();

xerces-c 3.1 XPath evaluation

I could not find much examples of evaluate XPath using xerces-c 3.1.
Given the following sample XML input:
<abc>
<def>AAA BBB CCC</def>
</abc>
I need to retrieve the "AAA BBB CCC" string by the XPath "/abc/def/text()[0]".
The following code works:
XMLPlatformUtils::Initialize();
// create the DOM parser
XercesDOMParser *parser = new XercesDOMParser;
parser->setValidationScheme(XercesDOMParser::Val_Never);
parser->parse("test.xml");
// get the DOM representation
DOMDocument *doc = parser->getDocument();
// get the root element
DOMElement* root = doc->getDocumentElement();
// evaluate the xpath
DOMXPathResult* result=doc->evaluate(
XMLString::transcode("/abc/def"), // "/abc/def/text()[0]"
root,
NULL,
DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, //DOMXPathResult::ANY_UNORDERED_NODE_TYPE, //DOMXPathResult::STRING_TYPE,
NULL);
// look into the xpart evaluate result
result->snapshotItem(0);
std::cout<<StrX(result->getNodeValue()->getFirstChild()->getNodeValue())<<std::endl;;
XMLPlatformUtils::Terminate();
return 0;
But I really hate that:
result->getNodeValue()->getFirstChild()->getNodeValue()
Has it to be a node set instead of the exact node I want?
I tried other format of XPath such as "/abc/def/text()[0]", and "DOMXPathResult::STRING_TYPE". xerces always thrown exception.
What did I do wrong?
I don't code with Xerces C++ but it seems to implement the W3C DOM Level 3 so based on that I would suggest to select an element node with a path like /abc/def and then simply to access result->getNodeValue()->getTextContent() to get the contents of the element (e.g. AAA BBB CCC).
As far as I understand the DOM APIs, if you want a string value then you need to use a path like string(/abc/def) and then result->getStringValue() should do (if the evaluate method requests any type or STRING_TYPE as the result type).
Other approaches if you know you are only interested in the first node in document order you could evaluate /abc/def with FIRST_ORDERED_NODE_TYPE and then access result->getNodeValue()->getTextContent().

jqgrid xml generating empty cell

I'm using this code to generate xml from my jqgrid's data:
var grid = $("#gridTable");
var dataFromGrid = grid.jqGrid ('getRowData');
var xml_string = '<rows>\n' + xmlJsonClass.json2xml ({rowTest:dataFromGrid}, '\t') +
'</rows>';
when the cell inside the grid is empty i get inside the xml tag "_EMPTY_STRING" ,
how can i change it to be just empty xml tag (like this: <cell1></cell1>)
while generating it ?
Thank's In Advance.
The most easy way to do this is just to append your code with the following line
xml_string = xml_string.replace(/>__EMPTY_STRING_<\//g, "><\/");
It will cut all __EMPTY_STRING_ strings.

Resources