JDOM: Get all element descendants (not only direct children) with a certain name - children

EDIT: problem solved. root and descendants had different namespaces.
So, I am trying to get all descendants of the root element with a certain name, "include".
Element root = doc.getRootElement();
Namespace ns = root.getNamespace();
ElementFilter ef = new ElementFilter("include", ns);
Iterator<Element> childrenIter = root.getDescendants(ef);
LinkedList<String> schemas = new LinkedList<String>();
while (childrenIter.hasNext()) {
Element el = childrenIter.next();
String schemaLocation = el.getAttributeValue("schemaLocation");
schemas.push(schemaLocation);
}
Unfortunately, while loop exits immediately, hasNext() returns null, even though there is an "include" element in the tree. Is there anything I'm doing wrong? I could maybe also use getChildren() and then go deep level by level, but this is much more convenient.
<wsdl:definitions ...>
<wsdl:types ...>
<xsd:schema ...>
<xsd:include schemaLocation="VsbKontoInfoGet_1.xsd"/>
</xsd:schema>
</wsdl:types>
...
</wsdl:definitions>
EDIT: problem solved. root and descendants had different namespaces.

Related

How to add a value to the existing element value and return it as a new value

This is the xml file.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<AtcoCode> System-Start-Date= 2018-05-16T12:35:48.6929328-04:00, " ", System-End-Date = 9999-12-31, " ", 150042010003</AtcoCode>
<NaptanCode>esxatgjd</NaptanCode>
<PlateCode>
</PlateCode>
<CleardownCode>
</CleardownCode>
<CommonName>Upper Park</CommonName>
<CommonNameLang>
</CommonNameLang>
<ShortCommonName>
</ShortCommonName>
<ShortCommonNameLang>
</ShortCommonNameLang>
<Landmark>Upper Park</Landmark>
<LandmarkLang>
</LandmarkLang>
<Street>High Road</Street>
<StreetLang>
</StreetLang>
<Crossing>
</Crossing>
<CrossingLang>
</CrossingLang>
<Indicator>adj</Indicator>
<IndicatorLang>
</IndicatorLang>
<Bearing>NE</Bearing>
<NptgLocalityCode>E0046286</NptgLocalityCode>
<LocalityName>Loughton</LocalityName>
<ParentLocalityName>
</ParentLocalityName>
<GrandParentLocalityName>
</GrandParentLocalityName>
<Town>Loughton</Town>
<TownLang>
</TownLang>
<Suburb>
</Suburb>
<SuburbLang>
</SuburbLang>
<LocalityCentre>1</LocalityCentre>
<GridType>U</GridType>
<Easting>541906</Easting>
<Northing>195737</Northing>
<Co-ordinates>51.64255,0.04944</Co-ordinates>
<StopType>BCT</StopType>
<BusStopType>MKD</BusStopType>
<TimingStatus>OTH</TimingStatus>
<DefaultWaitTime>
</DefaultWaitTime>
<Notes>
</Notes>
<NotesLang>
</NotesLang>
<AdministrativeAreaCode>080</AdministrativeAreaCode>
<CreationDateTime>2006-11-06T00:00:00</CreationDateTime>
<ModificationDateTime>2010-01-16T07:58:02</ModificationDateTime>
<RevisionNumber>5</RevisionNumber>
<Modification>rev</Modification>
<Status>act</Status>
</root>
How to achieve this?
Question: Create the path range index for the status element and fetch all the documents that has status del
after fetching all the documents, you need to create the new element called currentreservationnumber under RevisionNumber element.
The value of the currentrevisionnumber will be +1 to the RevisionNumber.
I think the warning about sequential numbers is related to system-wide unique numbers/ids (like Oracle sequence), so not a worry in this case?
If you only ever have one RevisionNumber, and you can find it without a path index, you can maybe get by with element-value query on the RevisionNumber since it's already indexed.
Given that you get the document somehow, it could be as simple as:
let $doc := fn:doc ('/foo.xml')
let $rev-node := $doc/root/RevisionNumber
return xdmp:node-insert-after ($rev-node, <currentreservationnumber>{$rev-node + 1}</currentreservationnumber>)
though remember to consider locking if you are doing a big query/update. And you might need to switch to node-replace if there is already a currentreservationnumber.

cannot find the correct syntax for this

I have a row in the table:
//*[contains(text(), 'Cape Town')]
and the delete graphic:
//*[contains(#id, 'DeleteLinkButton')]
in the table.
How do I click on //*[contains(#id, 'DeleteLinkButton')] of row //*[contains(text(), 'Cape Town')]?
If you want to find a node with XPath in relation to another node then in most cases you don't want to use an absolute path starting with / or even //, instead you would use a relative path like .//*[contains(#id, 'DeleteLinkButton')] as that would find descendants of the context node where the id attribute value contains DeleteLinkButton.
So with Javascript in the browser you would have e.g.
var myRow = ...;
and then you could call
myRow.ownerDocument.evaluate('.//*[contains(#id, 'DeleteLinkButton')]', myRow, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click();

I am having trouble adding elements to a referenced vector of a map

EDIT: Forgot to mention that my programming language is C++, and my IDE is Qt Creator.
I don't understand why I am having trouble adding elements to a referenced vector of a map (i.e. sometimes it works and sometimes it fails).
For example:
class C_html4_tags {
public:
C_html4_tags();
//.......
typedef std::vector<S_html_attr_value> TYPE_attr_values;
//.....
};
//...
C_html4_tags::C_html4_tags() {
//........
map<S_browser, TYPE_attr_values> attr_supported_attr_values_map;
S_browser dummy_browser; //a fake browser key for referencing a fully Html 4.01-compliant supported attr values list
dummy_browser.name = "Dummy";
//.....
TYPE_attr_values& attr_supported_attr_values = attr_supported_attr_values_map[dummy_browser];
//......
**attr_supported_attr_values = attr_supported_attr_values_map[dummy_browser];**
//...
**attr_supported_attr_values.clear();
attr_supported_attr_values_map.clear();**
//......
**attr_supported_attr_values = attr_supported_attr_values_map[dummy_browser];**
//...
**attr_supported_attr_values.clear();
attr_supported_attr_values_map.clear();**
}
I do the bolded lines multiple times with a bunch of different attributes, with very little difference between them, without a problem until reaching this one attribute (a_tabindex_attr), in which the IDE doesn't report anything wrong when running it normally (except "The program has unexpectedly finished." However, when debugging it, it now reports:
Signal received
The inferior stopped because it received a signal from the Operating
System.
Signal name : SIGSEGV Signal meaning : Segmentation fault
And the backtrace points to the attribute I mentioned above, on the line of code which does this:
attr_supported_attr_values.clear();
Now, after adding some debugging cout lines to the code, I learned that what's happening is, for some reason, even after doing:
attr_supported_attr_values.push_back(attr_value);
the vector object which is the returned mapped value of:
attr_supported_attr_values = attr_supported_attr_values_map[dummy_browser];
is not actually being changed when I push_back an S_html_attr_value object to the referenced vector. Now, I don't why that is, since I do pretty much the exact same thing in a bunch of other attributes' code before this one, without any problem, but for some reason now, on this one, it ain't adding the object to attr_supported_attr_values (which is a reference to the returned mapped value of 'dummy_browser'). And I know this for a fact, because I outputted the size of the internal mapped value object of the map (using an iterator for the map), and it was 0 after the call to push_back(). However, what is even more odd is, I ALSO outputted attr_supported_attr_values.size() after the call to push_back(), and that was 1! Now how could that be since they're both supposed to be the same object??
Note:
The full code of what I'm talking about is below (or at least the attribute code, minus the debugging statements...):
//a_tabindex_attr:
attr_desc = "Specifies the position of an <a> element in the\n"
"tabbing order for the current document.\n"
"The tabbing order defines the order in which\n"
"elements will receive focus when navigated by\n"
"the user via the keyboard. The tabbing order\n"
"may include elements nested within other elements.\n"
"Elements that may receive focus based on tabindex\n"
"adhere to the following rules:\n\n"
"1. Those elements that support this attribute and\n"
"assign a positive value to it are navigated first.\n"
"Navigation proceeds from the element with the\n"
"lowest tabindex value to the element with the\n"
"highest value. Values need not be sequential\n"
"nor must they begin with any particular value.\n"
"Elements that have identical tabindex values\n"
"should be navigated in the order they appear\n"
"in the character stream.\n"
"2. Those elements that do not support this\n"
"attribute or support it and assign it a value\n"
"of \"0\" are navigated next. These elements are\n"
"navigated in the order they appear in the\n"
"character stream.\n"
"3. Elements that are disabled do not participate\n"
"in the tabbing order.";
attr_supported_attr_values = attr_supported_attr_values_map[dummy_browser];
attr_value_desc = "A number you specify for the tab index/order.\n"
"It must be a value between 0 and 32767.";
attr_value_content = "<i>number</i>";
attr_value = C_html4_attributes_obj.getAttrValue(attr_value_desc, attr_value_content,
attr_value_supported_browsers,
attr_value_required, attr_value_deprecated,
attr_value_notes, attr_value_tips);
attr_value.is_relative = true;
attr_supported_attr_values.push_back(attr_value);
try {
N_init_class_members::initAttr(C_html4_attributes::attr_tabindex, a_tabindex_attr, attr_desc,
attr_supported_browsers, attr_supported_attr_values_map, attr_required,
attr_deprecated, attr_notes, attr_tips);
}
catch (const char* exc) {
string exc_str = "Error! Call to N_init_class_members::initAttr() from\n"
"constructor of C_html4_tags class. That function\n"
"reported the following exception:\n\n";
exc_str += exc;
throw (exc_str.c_str()); //re-throw exception
}
a_tabindex_attr.is_standard_attr = true;
a_tabindex_attr.is_optional_attr = true;
//cleanup from attribute operations so we can begin working on the next attribute:
C_html4_attributes_obj.clear(); //wipes the slate clean for all the supported attributes' properties except content
attr_desc.clear();
attr_supported_attr_values.clear();
attr_supported_attr_values_map.clear();
attr_value_desc.clear();
attr_value_content.clear();

Using XQUERY to retrieve attributes value

Is it possible to use XQUERY to retrieve the attributes filename from the following XML? I am trying to use /preFileDoc/inpXML/#filename but it doesn't work...
<?xml version="1.0"?>
<preFileDoc xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<senderId>ABC</senderId>
<receiverId>XYZ</receiverId>
<tranxCode>A001</tranxCode>
<inpXML version="1.0" encoding="UTF-8">
<soap-env:Envelope>
<soap-env:Header msgcode="SPPCONVAKT" orig-system="002FTB" refid="65355ff50a172064484bf9da64c1e245" timestamp="2009-02-11 21:00:10.741" filename="SPPCONVAKT20090128001.dat"/>
<soap-env:Body>
text1
text2
</soap-env:Body>
</soap-env:Envelope>
</inpXML>
</preFileDoc>
ps: Sometimes the filename attributes is sent as fileName in the incoming XML..thinking to retrieve value from attributes #filename OR #fileName.. can it achieve in single XQUERY? Thanks for advice...
I think your XPath is incomplete. The last child-step / in /preFileDoc/inpXML/#filename only matches attributes of the inpXML element, not its descendants.
One way to solve the problem would be the //-step:
/preFileDoc/inpXML//#filename
Note that this would find all attributes named filename in the soapenv:Body, too.
A more robust way would thus be to declare the soapenv prefix in the XQuery:
declare namespace soap-env="http://schemas.xmlsoap.org/soap/envelope/";
return /preFileDoc/inpXML//soap-env:Header/#filename
Finally, the different capitalizations of filename can be worked around by specifying both:
declare namespace soap-env="http://schemas.xmlsoap.org/soap/envelope/";
return /preFileDoc/inpXML//soap-env:Header/(#filename | #fileName)
You can take the union of multiple attributes. It will be unlikely that this attribute will appear multiple times with different casing, so that should always return a single node:
//soap-env:Header/#filename | //soap-env:Header/#fileName
Optionally, you could wrap it in parentheses, and add [1] behind it, to always take the first result.
(//soap-env:Header/#filename | //soap-env:Header/#fileName)[1]
If you replace the union with a comma, which creates a sequence instead of a document order node set, you can add a default as well at the end. Maybe not very usefull here, but perhaps in other situations:
(//soap-env:Header/#filename , //soap-env:Header/#fileName, "default.dat")[1]
HTH!
You need to respect and take into account the SOAP XML namespace!
Since I don't know what you're using, I cannot tell you how to do this - but there's the xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" on the root node, and your #filename attribute is on the <soap-env:Header .... /> node - so you need to include the XML namespace in your XQuery.
In .NET / C#, you could do it like this (using the "older" XmlDocument style which supports XPath directly):
// define test XML
string xmlContent =
#"<?xml version='1.0'?>
<preFileDoc xmlns:soap-env='http://schemas.xmlsoap.org/soap/envelope/'>
<senderId>ABC</senderId>
<receiverId>XYZ</receiverId>
<tranxCode>A001</tranxCode>
<inpXML version='1.0' encoding='UTF-8'>
<soap-env:Envelope>
<soap-env:Header msgcode='SPPCONVAKT' orig-system='002FTB' refid='65355ff50a172064484bf9da64c1e245' timestamp='2009-02-11 21:00:10.741' filename='SPPCONVAKT20090128001.dat'/>
<soap-env:Body>
text1
text2
</soap-env:Body>
</soap-env:Envelope>
</inpXML>
</preFileDoc>";
// create XmlDocument and load test data
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlContent);
// define XML namespace manager and add the SOAP namespace to it
XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
// use XPath and the XML namespaces to grab the <Header> node
// the first two nodes <preFileDoc> and <inpXML> are not inside any explicit
// XML namespace
// but the next two (<Envelope> and <Header>) are in the "soap" XML namespace
XmlNode header = doc.SelectSingleNode("/preFileDoc/inpXML/soap:Envelope/soap:Header", mgr);
// read the "filename" attribute from the header node
if(header != null && header.Attributes["filename"] != null)
{
string fileName = header.Attributes["filename"].Value;
}

TreeNode.Remove doesn't work !

I have a strange problem. Let's look at that code:
TreeNode tn = TreeView1.FindNode("2009/08/12 (1)"); //OK, the Node is found
Now, I need to delete that node:
(IT DOESN'T WORK !)
(e.g. (I know that I don't need to use TreeView1.FindNode() method, but i = -1))
TreeNode tn1 = TreeView1.FindNode(tn.ValuePath);
int i = TreeView1.Nodes.IndexOf(tn1);
or
TreeView1.Nodes.Remove(tn);
The problem is, the codes above doesn't work, I mean, the node isn't removed, why ?
The TreeView looks like that:
alt text http://img130.imageshack.us/img130/230/71970321.png
It seems that the TreeView control in .net only allows to remove First Level Nodes, so if the node you are trying to delete is not this kind of node, you need to delete it trough its parent, using something like this:
Dim Padre As TreeNode = TreeView1.SelectedNode.Parent
If (Padre Is Nothing) Then
TreeView1.Nodes.Remove(TreeView1.SelectedNode)
Else
Padre.ChildNodes.Remove(TreeView1.SelectedNode)
End If
Hope it helps!
Are you sure that you've selected the node properly? If TreeView1.Nodes.IndexOf(tn1) is returning -1, this indicates the node can't be found.

Resources