xmlserializer deserialize list containing attributes - list

I have xml that part of structure looks like this:
<IDList>
<ValuesList ID="1">
<Value>1</Value>
<Value>2</Value>
<Value>3</Value>
</ValuesList>
<ValuesList ID="2">
<Value>1</Value>
<Value>2</Value>
<Value>3</Value>
</ValuesList>
</IDList>
What should be model classes for xmlserializer, so I could deserialize it properly?
On the level of IDList it's quite easy:
[XmlArray("IDList")]
[XmlArrayItem("ValuesList")]
public List<CValuesList> idList = new List<CValuesList>();
but how can I do it when the array element has extra xml attribute?
I tried to do ot in the way shown here:
http://www.codemeit.com/xml/c-xmlserializer-add-an-attribute-to-an-array-element.html
but it didn't worked for me. The elements of the array haven't been deserialized.

There is no simple way to do that.
A good solution would be to create an object that contains a list and your properties and inherit/implements IXmlSerializable.
I've seen some kind of quick and dirty way on this site: http://funcakes.posterous.com/adding-elements-to-lists-in-the-xmlserializer. Since the object doesn't inherit from ISerializable, it won't be serialized as a list by the serializer.

Related

XSLT copy from external document

In XSLT 2.0 I am transforming a tei-xml document into HTML. In that transformationI need content from another document: I want to copy/transform a small set of nodes from the second document into the HTML output.
While processing the principal tei document I get the id and assign it to a variable:
<xsl:variable name="licenseid" select="./replace(#corresp,'#','')"/>
Then I go out to the other document and fetch the node using the variable, with the returned node assigned to a variable:
<xsl:variable name="licenseloc" select="doc(concat($somepath,'includes_sourcedesc.xml'))//tei:list[#type='copyright_type']/tei:item[#xml:id=$licenseid]"/>
This node I obtain looks like this:
<list type="copyright_type">
<item xml:id="copyright-cc-by-nc-sa-4.0">
<desc xml:lang="en">This work is made by available the author under the
<ref target="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike
4.0 International License</ref>.</desc>
</item>
</list>
And I want to transform it (from desc) to this:
<span>This work is made by available by the author under the
<a href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike
4.0 International License</a>.</span>
If this were in my 'current' tei document I would handle it through templates, but I'm unsure how to copy and transform the nested layers from within a different 'current' document.

Adding xml attribute in spring rest xml response

How to add inner attribute to spring REST webservice response?
Sample xml returned by my webservice:
<books>
<bookId>5</bookId>
<bookName>testBook</bookName>
</books>
I want to use book id as xml attribute for bookName:
<books>
<bookName id="5">testBook</bookName>
</books>
Any suggestion?
Based on how your java types are defined you can either annotate your classes with #XmlAttribute or may need to write your custom XmlAdapter

Loading xml in non-binary tree

I have created non-binary tree in order to load xml data in it and be used later for dialogue system.I want to implement the dialogue systems like in fallout where every answer can contain 4 different nodes with another answers.So far i created xml with the sentences
<Dialogue>
<Node>Hello,what do you want?</Node>
<Leaf>Nothing</Leaf>
<Leaf>Really?</Leaf>
<Branch>
<Node>Really?</Node>
<Leaf>Yes></Leaf>
<Branch>
<Node>No</Node>
<Leaf>Why not?</Leaf>
</Branch>
</Branch>
</Dialogue>
here node in the tree in c++ is represented as parent Leafs are child and below first branch node is child of the upper node.I find difficultis to load the xml data in tree with this structure so do you have ideas for better structures?
With your current structure of XML, you'll find it tricky to implement this, I'll suggest one option..
<Dialogue>
<Node id="root">
<Prompt>Hello,what do you want?</Prompt>
<Response>
<match>Nothing</match>
<Branch node_id="nothing"/>
</Response>
: <!-- more Response nodes -->
</Node>
<Node id="nothing">
<Prompt>Really?</Prompt>
<Response>
<match>Yes</match>
<Branch node_id="nothing.yes"/>
</Response>
<Response>
<match>Actually...</match>
<Branch node_id="nothing.actually"/>
</Response>
</Node>
<Node id="nothing.yes">
<Prompt>Why not?</Prompt>
: <!-- Response Nodes -->
</Node>
<Node id="nothing.actually">
<Prompt>Okay, what then?</Prompt>
: <!-- Response Nodes -->
</Node>
</Dialogue>
In reality, with this type of data, you need a map to store each "Node", where a Node is a prompt with a set of responses (the key to the map is the id of Node - which you have to guarantee as being unique. Depending on which response matches, you can then then find the node in the map and hand control to that etc. Probably a little easier to deal with than a tree? Also give you the possibility of re-using states... NOTE: the XML above is really verbose, you can trim it down with attributes, my intention was to simply get the idea across...
It's an option to consider I guess...

How are attributes parsed in Boost.PropertyTree?

Say I have this XML format:
<Widget type="SomeWidget" name="foo">
<Event name="onmouseover">
dostuff();
</Event>
</Widget>
How do I read the attributes using Boost.PropertyTree?
If xml has such content:
<mode fullscreen="true">mode xxx</mode>
Use boost::property code:
get<string>("mode.<xmlattr>.fullscreen")
Oh yeah, it's ugly!
If your problem is to get attributes:
The attributes of an XML element are
stored in the subkey . There
is one child node per attribute in the
attribute node. Existence of the
node is not guaranteed or
necessary when there are no
attributes.
From the doc http://www.boost.org/doc/libs/1_44_0/doc/html/boost_propertytree/parsers.html#boost_propertytree.parsers.xml_parser
So just get them from the <xmlattr> key in the path.

MSXML Select Nodes Not Working

I am working on an automated testing app, and am currently in the process of writing a function that compares values between two XML files that should be identical, but may not be. Here is a sample of the XML I'm trying to process:
<?xml version="1.0" encoding="utf-8"?>
<report xmlns="http://www.**.com/**">
<subreport name="RBDReport">
<record rowNumber="1">
<field name="Time">
<value>0</value>
</field>
<field name="Reliability">
<value>1.000000</value>
</field>
<field name="Unreliability">
<value>0.000000</value>
</field>
<field name="Availability">
<value> </value>
</field>
<field name="Unavailability">
<value> </value>
</field>
<field name="Failure Rate">
<value>N/A</value>
</field>
<field name="Number of Failures">
<value> </value>
</field>
<field name="Total Downtime">
<value> </value>
</field>
</record>
(Note there may be multiple <subreport> elements and within those, multiple <record> elements.)
What I'd like is to extract the <value> tags of two documents and then compare their values. That part I know how to do. The problem is the extraction itself.
Since I'm stuck in C++, I'm using MSXML, and have written a wrapper to allow my app to abstract away the actual XML manipulation, in case I ever decide to change my data format.
That wrapper, CSimpleXMLParser, loads an XML document and sets its "top record" to the document element of the XML document. (CRecord being an abstract class with CXMLRecord one of its subclasses, and which gives access to child records singularly or by group, and also allowing access to the "value" of the Record (values for child elements or attributes, in the case of CXMLRecord.) A CXMLRecord contains an MSXML::MSXMLDOMNodePtr and a pointer to an instance of a CSimpleXMLParser.) The wrapper also contains utility functions for returning children, which the CXMLRecord uses to return its child records.
In my code, I do the following (trying to return all <subreport> nodes just to see if it works):
CSimpleXMLParser parserReportData;
parserReportData.OpenXMLDocument(strPathToXML);
bool bGetChildrenSuccess = parserReportData.GetFirstRecord()->GetChildRecords(listpChildren, _T("subreport"));
This is always returning false. The meat of the implementation of CXMLRecord::GetChildRecords() is basically
MSXML2::IXMLDOMNodeListPtr pListChildren = m_pParser->SelectNodes(strPath, m_pXMLNode);
if (pListChildren->Getlength() == 0)
{
return false;
}
for (long l = 0; l < pListChildren->Getlength(); ++l)
{
listRecords.push_back(new CXMLRecord(pListChildren->Getitem(l), m_pParser));
}
return true;
And CSimpleXMLParser::SelectNodes() is:
MSXML2::IXMLDOMNodeListPtr CSimpleXMLParser::SelectNodes(LPCTSTR strXPathFilter, MSXML2::IXMLDOMNodePtr pXMLNode)
{
return pXMLNode->selectNodes(_bstr_t(strXPathFilter));
}
When run, the top record is definitely being set to the <report> element properly. I can do all sorts of things with it, like getting its child nodes (through the MSXML interface, not through my wrapper) or its name, etc. I know that my wrapper can work, because I use it elsewhere in the app for parsing an XML configuration file, and that works flawlessly.
I thought maybe I was doing something faulty with the XPath query expression, but every permutation I could think of gives no joy. The MSXML::IXMLDOMNodeListPtr returned by IXMLDOMNodePtr::SelectNodes() is always of length 0 when I try to deal with this XML file.
This is driving me crazy.
I'm used to doing this with .NET's XmlDocument objects, but I think the effect is the same here:
If the XML document includes a namespace -- even an unnamed one -- then the Xpath query has to use one as well. So, you'll have to add the namespace to the XMLDoument which you might as well give a name in the code, and the include the prefix in the XPATH query (it doesn't matter that the prefixes are different between the xml document and the xpath, as long as the namespaces sort it out)
SO, while you are using an XPath like /report/subreport/record/field/value, you actually need to first set the namespace of your document:
pXMLDoc->setProperty(_bstr_t("SelectionNamespaces"),
_bstr_t("xmlns:r="http://www.**.com/**"));
and then selectNodes() using /r:report/r:subreport/r:record/r:field/r:value
I see no reference to a namespace when you're selecting nodes. I'd expect this to be the fundamental problem.