Can't get XPathSelectElements to work with XElement - xpath

I am creating an in-memory Xml tree using XElement. Here is a sample of my xml:
<Curve>
<Function>createCurve</Function>
<Parameters>
<Input>
<BaseCurve>
<CurveType Type="String">16fSmoothCurve</CurveType>
<Ccy Type="String">USD</Ccy>
<Tenors>
<Item Type="String">1M</Item>
<Item Type="String">3M</Item>
<Item Type="String">1U</Item>
<Item Type="String">Z1</Item>
</Tenors>
<Rates>
<Item Type="String">.02123</Item>
<Item Type="String">.02214</Item>
<Item Type="String">.021234</Item>
<Item Type="String">.02674</Item>
</Rates>
</BaseCurve>
</Input>
</Parameters>
</Curve>
I am creating the xml by chaining together XElements. For example,
var root = new XElement("Curve",
new XElement("Function", "createCurve"),
new XElement("Parameters"), etc);
I would then like to query the XElement via XPath. For example,
var tenors = root.XPathSelectElements("//Tenors/Item");
var rates = root.XPathSelectElements("//Rates/Item");
I can successfully select a single element, for example,
var firstTenor = root.XPathSelectElement("//Tenors/Item");
var firstRate = root.XPathSelectElement("//Rates/Item");
However, trying to select multiple elements give me 0 results.
I've tried creating an XDocument and querying off of that however I get the same results. I've also tried adding an XDeclaration to the beginning of the tree but no luck.
Why can I not query multiple elements from my XElement tree?
Thanks!
Drew

Use XmlNodeList:
XmlNodeList nodesXml = root.SelectNodes("//Tenors/Item");
foreach (XmlNode item in nodList)
{
var tenors = item.InnerText;
}
That what I do, and it works perfect.

Related

Creating Dynamic XML request body in Jmeter

I am new to Jmeter and need some help with creating a dynamic Soap message.I am trying to post the below XML body as HTTP request in Jmeter -
<soap:Envelope xmlns:soap="http://XXXXXsoap-envelope" xmlns:tem="http://XXXXX/“>
<soap:Header/>
<soap:Body>
<tem:ProcessMessage>
<tem:message>
<![CDATA[
<LoyaltyMessages xmlns:xsi="http://www.w3.org/XXXX/XMLSchema-instance" xmlns:xsd="hXXXX/XMLSchema" XID="4" YYY="4186" ZZZ="998" PPP="1" LLLL="2" DateTime="2022-09-13T13:30:12" LLL="1">
<TransactionRequests>
<TransactionRequest Type="0">
<Request JJJ="0" SSS="1">
<Items>
<Item SeqID="1" ItemCode="1145677" DepCode="105" SaleType="0" QtyType="1" Qty="2" NetPrice="1400" NetAmount="2800"/>
<Item SeqID="2" ItemCode="1145677" DepCode="105" SaleType="0" QtyType="1" Qty="2" NetPrice="1400" NetAmount="2800"/>
</Items>
<Total TotalAmount="28.00" TotalNumberOfItems="2"/>
</Request>
</TransactionRequest>
</TransactionRequests>
</LoyaltyMessages>
]]>
</tem:message>
</tem:ProcessMessage>
</soap:Body>
</soap:Envelope>
I want to substitute the tags within Items field with a dynamic body that can have upto 50-100 items with incrementing SeqID so it looks like -
<Items>
<Item SeqID="1" ItemCode="${ItemCode}" DepCode="${DepCode}" SaleType="${SaleType}" QtyType="${QtyType}" Qty="${Qty}" NetPrice="${NetPrice}" NetAmount="${NetAmount}"/>
<Item SeqID="2" ItemCode="${ItemCode}" DepCode="${DepCode}" SaleType="${SaleType}" QtyType="${QtyType}" Qty="${Qty}" NetPrice="${NetPrice}" NetAmount="${NetAmount}"/>
<Item SeqID="3" ItemCode="${ItemCode}" DepCode="${DepCode}" SaleType="${SaleType}" QtyType="${QtyType}" Qty="${Qty}" NetPrice="${NetPrice}" NetAmount="${NetAmount}"/>
</Items>
I am using a CSV dataset config but it adds the same values for all item list as it is the same request. Also not sure how to achieve multiple tag blocks inside Items tag.
You can generate dynamic block of Items using JSR223 PreProcessor and the Groovy code like:
Change your request body to:
<soap:Envelope xmlns:soap="http://XXXXXsoap-envelope" xmlns:tem="http://XXXXX/">
<soap:Header/>
<soap:Body>
<tem:ProcessMessage>
<tem:message>
<![CDATA[
<LoyaltyMessages xmlns:xsi="http://www.w3.org/XXXX/XMLSchema-instance" xmlns:xsd="hXXXX/XMLSchema" XID="4" YYY="4186" ZZZ="998" PPP="1" LLLL="2" DateTime="2022-09-13T13:30:12" LLL="1">
<TransactionRequests>
<TransactionRequest Type="0">
<Request JJJ="0" SSS="1">
<Items>
${items}
</Items>
<Total TotalAmount="28.00" TotalNumberOfItems="${numberOfItems}"/>
</Request>
</TransactionRequest>
</TransactionRequests>
</LoyaltyMessages>
]]>
</tem:message>
</tem:ProcessMessage>
</soap:Body>
</soap:Envelope>
Add JSR223 PreProcessor as a child of the HTTP Request sampler and put the following code into "Script" area
def numberOfItems = 10
def items = new StringBuilder()
1.upto(numberOfItems, { index ->
items.append('<Item SeqID="')
.append(index)
.append('" ItemCode="')
.append(vars.get('ItemCode'))
.append('"')
.append('"')
.append(' DepCode="')
.append(vars.get('DepCode'))
.append('" SaleType="')
.append(vars.get('SaleType'))
.append('" QtyType="')
.append(vars.get('QtyType'))
.append(" Qty=")
.append(vars.get('Qty'))
.append('" NetPrice="')
.append(vars.get('NetPrice'))
.append('" NetAmount="')
.append(vars.get('NetAmount'))
.append('"/>')
.append(System.getProperty('line.separator'))
})
vars.put('items', items.toString())
vars.put('numberOfItems', numberOfItems as String)

How to set programatically a selector to a checkbox

I need to set a selector to checkboxes that are created programatically, this way:
var cbAll = new CheckBox(Activity);
LinearLayout.LayoutParams llAll = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
cbAll.Text = "All zones";
llAll.LeftMargin = 27;
llAll.TopMargin = 24;
cbAll.ButtonDrawable = //what to put here?
My selector (named cb_edit.xml) in drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/cb_active" android:state_checked="true" />
<item android:drawable="#drawable/cb_default" android:state_checked="false"/>
</selector>
i don't know what exactly you trying.but if u setting background then try this
cbAll.SetBackgroundResource( Resource.Drawable.cb_edit);
First, add an XML into your drawable folder:
CheckBoxDrawable.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="#drawable/CheckedImage" />
<item android:state_checked="false" android:drawable="#drawable/UnCheckedImage" />
</selector>
Then declare the checkbox and set the button drawable to it something like this:
Checkbox btnOption = new Checkbox(context);
btnOption.SetButtonDrawable(Resource.Drawable.CheckBoxDrawable);
That should make it work in case it does not revert

Table populated by Service SelectionListener

I am struggling getting a working selectionListener on a Read-Only Table populated by a Service (exposed in the DataControls). No Entity / VO / ApplicationModule involved. I use ADF 11.1.1.5
my jsff:
<af:panelStretchLayout id="psl1">
<f:facet name="center">
<af:table value="#{bindings.DocumentMetadatenDTO.collectionModel}"
var="row" rows="#{bindings.DocumentMetadatenDTO.rangeSize}"
emptyText="Empty"
fetchSize="#{bindings.DocumentMetadatenDTO.rangeSize}"
rowBandingInterval="0"
rowSelection="single" id="t1"
selectionListener="#{pageFlowScope.documentSearchBean.documentTableSelectionListener}"
partialTriggers="::psl1">
my pageFlowScoped Bean:
public void documentTableSelectionListener(SelectionEvent selectionEvent) {
RichTable table = (RichTable) selectionEvent.getSource();
Object selection = table.getSelectedRowData(); // **returns null**
}
my bindings definition:
<executables>
<methodIterator Binds="getDocuments.result"
DataControl="DocumentSearchServiceMock" RangeSize="-1"
BeanClass="****.model.DocumentMetadatenDTO"
id="getDocumentsIterator"/>
</executables>
<bindings>
<methodAction id="getDocuments" RequiresUpdateModel="true"
Action="invokeMethod" MethodName="getDocuments"
IsViewObjectMethod="false"
DataControl="DocumentSearchServiceMock"
InstanceName="DocumentSearchServiceMock.dataProvider"
ReturnName="data.DocumentSearchServiceMock.methodResults.getDocuments_DocumentSearchServiceMock_dataProvider_getDocuments_result">
<NamedData NDName="query"
NDValue="#{pageFlowScope.documentSearchBean.documentSearchQuery}"
NDType="****.model.DocumentSearchQuery"/>
</methodAction>
<tree IterBinding="getDocumentsIterator" id="DocumentMetadatenDTO">
<nodeDefinition DefName="****.model.DocumentMetadatenDTO"
Name="DocumentMetadatenDTO0">
<AttrNames>
<Item Value="id"/>
<Item Value="creationDate"/>
<Item Value="zielArchive"/>
<Item Value="documentType"/>
<Item Value="documentSource"/>
</AttrNames>
</nodeDefinition>
</tree>
<attributeValues IterBinding="getDocumentsIterator" id="id">
<AttrNames>
<Item Value="id"/>
</AttrNames>
</attributeValues>
</bindings>
Does anybody have any idea?
PS: I already tried to update the iterator current row using this example from Oracle, and then selecting an attribute value from the bindings, without success neither.
Your scopes are messed up.
References to components on the page (such as the table) shouldn't be in a pageFlowScope bean.

Use of text() function when using xPath in dom4j

I have inherited an application that parses xml using dom4j and xPath:
The xml being parsed is similar to the following:
<cache>
<content>
<transaction>
<page>
<widget name="PAGE_ID">WRK_REGISTRATION</widget>
<widget name="TRANS_DETAIL_ID">77145</widget>
<widget name="GRD_ERRORS" />
</page>
<page>
<widget name="PAGE_ID">WRK_REGISTRATION</widget>
<widget name="TRANS_DETAIL_ID">77147</widget>
<widget name="GRD_ERRORS" />
</page>
<page>
<widget name="PAGE_ID">WRK_PROCESSING</widget>
<widget name="TRANS_DETAIL_ID">77152</widget>
<widget name="GRD_ERRORS" />
</page>
</transaction>
</content>
</cache>
Individual Nodes are being searched using the following:
String xPathToGridErrorNode = "//cache/content/transaction/page/widget[#name='PAGE_ID'][text()='WRK_DNA_REGISTRATION']/../widget[#name='TRANS_DETAIL_ID'][text()='77147']/../widget[#name='GRD_ERRORS_TEMP']";
org.dom4j.Element root = null;
SAXReader reader = new SAXReader();
Document document = reader.read(new BufferedInputStream(new ByteArrayInputStream(xmlToParse.getBytes())));
root = document.getRootElement();
Node gridNode = root.selectSingleNode(xPathToGridErrorNode);
where xmlToParse is a String of xml similar to the excerpt provided above.
The code is trying to obtain the GRD_ERROR node for the page with the PAGE_ID and TRANS_DETAIL_ID provided in the xPath.
I am seeing an intermittent (~1-2%) failure (returned node is null) of this selectSingleNode request even though the requested node is in the xml being searched.
I know there are some gotchas associated with using text()= in xPath and was wondering if there was a better way to format the xPath string for this type of search.
From your snippets, there is a problem regarding GRD_ERRORS vs. GRD_ERRORS_TMP and WRK_REGISTRATION vs. WRK_DNA_REGISTRATION.
Ignoring that, I would suggest to rewrite
//cache/content/transaction/page
/widget[#name='PAGE_ID'][text()='WRK_DNA_REGISTRATION']
/../widget[#name='TRANS_DETAIL_ID'][text()='77147']
/../widget[#name='GRD_ERRORS_TEMP']
as
//cache/content/transaction/page
[widget[#name='PAGE_ID'][text()='WRK_REGISTRATION']]
[widget[#name='TRANS_DETAIL_ID'][text()='77147']]
/widget[#name='GRD_ERRORS']
Just because it makes the code, in my eyes, easier to read, and expresses what you seem to mean more clearly: “the page element that has children with these conditions, and then take the widget with this #name.” Or, if that is closer to how you think about it,
//cache/content/transaction/page/widget[#name='GRD_ERRORS']
[preceding-sibling::widget[#name='PAGE_ID'][text()='WRK_REGISTRATION']]
[preceding-sibling::widget[#name='TRANS_DETAIL_ID'][text()='77147']]

Problem with namespace and libxml when i use Xpath

i've got a problem when i'm using libxml with XPath. I want to parse an youtube playlist :
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/'
xmlns:media='http://search.yahoo.com/mrss/'
xmlns:batch='http://schemas.google.com/gdata/batch'
xmlns:yt='http://gdata.youtube.com/schemas/2007'
xmlns:gd='http://schemas.google.com/g/2005'
gd:etag='W/"Dk8DRn47eCp7ImA9WxRQGEk."'>
<id>tag:youtube,2008:user:andyland74:playlists</id>
<updated>2008-07-21T16:43:25.232Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://gdata.youtube.com/schemas/2007#playlistLink'/>
<title>Playlists of andyland74</title>
<logo>http://www.youtube.com/img/pic_youtubelogo_123x63.gif</logo>
<link rel='related' type='application/atom+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74?v=2'/>
<link rel='alternate' type='text/html'
href='http://www.youtube.com/profile_play_list?user=andyland74'/>
<link rel='http://schemas.google.com/g/2005#feed'
type='application/atom+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists?v=2'/>
<link rel='http://schemas.google.com/g/2005#post'
type='application/atom+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists?v=2'/>
<link rel='http://schemas.google.com/g/2005#batch'
type='application/atom+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists/batch?v=2'/>
<link rel='self' type='application/atom+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists?...'/>
<link rel='service' type='application/atomsvc+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists?alt=...'/>
<author>
<name>andyland74</name>
<uri>http://gdata.youtube.com/feeds/api/users/andyland74</uri>
</author>
<generator version='2.0'
uri='http://gdata.youtube.com/'>YouTube data API</generator>
<openSearch:totalResults>3</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>25</openSearch:itemsPerPage>
<entry gd:etag='W/"Dk8DRn47eCp7ImA9WxRQGEk."'>
<id>tag:youtube,2008:user:andyland74:playlist:8BCDD04DE8F771B2</id>
<published>2007-11-04T17:30:27.000-08:00</published>
<updated>2008-07-15T12:33:20.000-07:00</updated>
<app:edited xmlns:app='http://www.w3.org/2007/app'>2008-07-15T12:33:20.000-07:00</app:edited>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://gdata.youtube.com/schemas/2007#playlistLink'/>
<title>My New Playlist Title</title>
<summary>My new playlist Description</summary>
<content type='application/atom+xml;type=feed'
src='http://gdata.youtube.com/feeds/api/playlists/8BCDD04DE8F771B2?v=2'/>
<link rel='related' type='application/atom+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74?v=2'/>
<link rel='alternate' type='text/html'
href='http://www.youtube.com/view_play_list?p=8BCDD04DE8F771B2'/>
<link rel='self' type='application/atom+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists/8BCDD04DE8F771B2?v=2'/>
<link rel='edit' type='application/atom+xml'
href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists/8BCDD04DE8F771B2?v=2'/>
<author>
<name>andyland74</name>
<uri>http://gdata.youtube.com/feeds/api/users/andyland74</uri>
</author>
<yt:countHint>9</yt:countHint>
</entry>
</feed>
when i use the following xpath expression "/feed", the xmlXPathEvalExpression say me that i doesnt find.
if i remove all the xmlns attributes of feed it works. How could i make it work even with xmlns attributes ?
i use libxml with objective-C
I ran into a similar issue when trying to use libxml-ruby to parse through xml. From http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/XPath.html:
To find nodes you must define the atom
namespace for libxml. One way to do
this is:
node = doc.find('atom:title', 'atom:http://www.w3.org/2005/Atom')
Alternatively, you can register the
default namespace like this:
doc.root.namespaces.default_prefix = 'atom' node = doc.find('atom:title')
Either way works, but registering makes sense if you're going to be using the methods a lot. Then you can just reference items like 'atom:title'.
I am using the XPathQuery wrapper around xmlXPathEvalExpression which makes it harder to go the xmlXpathRegisterNS route.
If you are querying for the fields directly, you probably do not care about the namespaces - it doesn't matter for my app. So, I just modified the XML before I process it.
NSString *xmlString = [[NSString alloc] initWithData:originalXMLData encoding:NSUTF8StringEncoding];
NSString *modifiedXMLString = [xmlString stringByReplacingOccurrencesOfString:#"xmlns=" withString:#"foobar="];
NSData *modifiedXMLData = [modifiedXMLString dataUsingEncoding:NSUTF8StringEncoding];
Now you can use modifiedXMLData in xmlXPathEvalExpression or PerformXMLXPathQuery if you use XPathQuery.
You didn't post your query code, but it sounds like you aren't registering the namespaces with your XpathContext. Here's the API docs for xmlXPathRegisterNS, I believe it will do what you're looking for. It won't let you register a default namespace, so you'll need to change your XPath expression to /feed:feed or the like.
To use a default namespace just register the namespace xlmns= and then use /xmlns:feed in your query.
After some research, I found the following solution that just works like NSXMLDocument path queries:
when xml documents declare a default namespace without a prefix, like
xmlns="..."
simple xpaths queries fail, like
xpath: /node
that's because xmlXPathEvalExpressionexpects some kind of default namespace prefix but there is none.
One approach is to fix the missing prefix (like GDataXML does) but that requires all xpaths to use this prefix, like
xpath: /__def_ns:node
But this is not how xpath's and NSXMLDocument works.
The following solution (based on a DDXMLNode) goes to the root node and scans for a namesepace without a prefix.
Then all nodes below are being traversed and if they belong to that namespace, it is being removed.
This is just like if there was no namespace in the first place.
- (void)fixNameSpace
{
xmlNodePtr nodePtr = (xmlNodePtr)self->genericPtr;
xmlNsPtr ns = nodePtr->nsDef;
xmlNsPtr defaultNs = NULL;
while(ns != NULL)
{
if (ns->prefix == NULL)
{
defaultNs = ns;
break;
}
ns = ns->next;
}
if (defaultNs)
[self resetDefaultNs:defaultNs];
}
- (void)resetDefaultNs:(xmlNsPtr)defaultNs
{
xmlNodePtr nodePtr = (xmlNodePtr)self->genericPtr;
xmlNsPtr ns = nodePtr->ns;
if (ns && ns == defaultNs)
xmlSetNs(nodePtr, NULL);
for (NSXMLNode* child in self.children)
[child resetDefaultNs:defaultNs];
}

Resources