error at tinyxml when deserialize - c++

I have the following xml:
<Name />
<Sur> mmm </Sur>
When I deserialize I wrote:
TiXmlElement* section;
section=handle.FirstChild("Name").ToElement()
if (section) {}
The problem is that the if condition is runned though field Name is null. WHY? Where am I wrong?
Appreciate. THX

Maybe you should define a root element of your XML code, like <Person>:
<Person>
<Name />
<Sur> mmm <Sur />
</Person>

Related

rapidxml weird parsing for one specific node

I've been looking for hours a solution to my (simple ?) problem but I cannot find anyone who encountered this. I'm using latest version of rapidxml(1.13).
I'm currently trying to create a tile-based engine and I need to read tmx file.
I'm been using rapidxml for a while and so far everything was great. It was able to read every node perfectly and with an expected behavior. But I came across one node it has a problem with.
This is my tmx file :
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.5" tiledversion="1.6.0" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="12" nextobjectid="1">
<tileset firstgid="1" source="../../../Tile_engine/Tile_engine/sprite/[Base]BaseChip_pipo.tsx"/>
<tileset firstgid="1065" source="../../../Tile_engine/Tile_engine/sprite/collision.tsx"/>
<layer id="4" name="background" width="100" height="100">
<properties>
<property name="bg" type="bool" value="false"/>
</properties>
<data encoding="csv">
//I've removed the data for clearer view
</data>
</layer>
<layer id="6" name="object" width="100" height="100">
<properties>
<property name="isSolid" type="bool" value="true"/>
</properties>
<data encoding="csv">
//I've removed the data for clearer view
</data>
</layer>
<layer id="9" name="front" width="100" height="100">
<properties>
<property name="isSolid" type="bool" value="false"/>
</properties>
<data encoding="csv">
//I've removed the data for clearer view
</data>
</layer>
<layer id="11" name="collision" width="100" height="100">
<data encoding="csv">
//I've removed the data for clearer view
</data>
</layer>
</map>
In order to debug, I'm using a basic read with rapidxml :
xml_document<> doc;
xml_node<> * root_node;
// Read the xml file into a vector
ifstream theFile ("sprites/map_wtf.tmx");
vector<char> buffer((istreambuf_iterator<char>(theFile)), istreambuf_iterator<char>());
buffer.push_back('\0');
// Parse the buffer using the xml file parsing library into doc
doc.parse<0>(&buffer[0]);
// Find our root node
root_node = doc.first_node("map");
When I try to read (and count) the layer node for example :
int count_node(0);
for(xml_node<> * child = root_node->first_node("layer"); child != nullptr; child = child->next_sibling())
count_node++;
cout << count_node;
The output is correct and gives me 4.
But when I try to read the tileset node, the output gives me 6.
So I've assumed the behavior is link to the /> at the end of the tileset node (<tileset firstgid="1" source="../../../Tile_engine/Tile_engine/sprite/[Base]BaseChip_pipo.tsx"/>).
Since the nested property node has the same pattern (<property name="bg" type="bool" value="false"/>), I've tried this code :
int count_node(0);
for(xml_node<> * child = root_node->first_node("layer")->first_node("properties")->first_node("property"); child != nullptr; child = child->next_sibling())
count_node++;
cout << count_node;
who gives me the correct output aka : 1.
I've tried different parsing options for the line doc.parse<0>(&buffer[0]) but nothing works. I've also read the content of the buffer during theses tests and it was correct.
I must have the wrong way to read the file but I cannot understand why this script reads layer node and property node fine, but not the tileset ones.
Can anyone help me ?
Thanks !
The question is based on a misunderstanding about the result of
xml_node<> * child = root_node->first_node("layer");
child = child->next_sibling();
The child = child->next_sibling() returns the next node on the same level irregardless of the node name or any other constraint that was applied during the root_node->first_node("layer") selection.
However, the next_sibling signature is basically the same as the first_node signature, so it can be used to apply criteria to the next sibling node to be found.
So the (untested) approach would be like
int count_node(0);
for(xml_node<> * child = root_node->first_node("tileset"); child != nullptr; child = child->next_sibling("tileset"))
count_node++;
cout << count_node;

XSLT - select a node from a complex xml file

I have an XML file below where I need to get the text inside of the <Description> tag under the <Checklist> tag where the <Sequence> tag has the text 40. How to achieve it?
<?xml version="1.0" encoding="UTF-8"?>
<SyncMaintenanceOrder>
<DataArea>
<MaintenanceOrder>
<MaintenanceOrderHeader>
<DocumentID>
<ID accountingEntity="AT">1105442</ID>
</DocumentID>
<Description>Routine Bridge Inspection - S6</Description>
<PriorityCode>2</PriorityCode>
<ReportedDateTime>2020-04-29T20:21:27Z</ReportedDateTime>
</MaintenanceOrderHeader>
<MaintenanceOrderLine>
<LineNumber>10</LineNumber>
<RemainingDuration>PT8H0M0S</RemainingDuration>
<ActivityDeferredIndicator>false</ActivityDeferredIndicator>
<UserArea>
<EamCheckListInfo>
<CheckList>
<CheckListItem>
<Sequence>40</Sequence>
<Description>Half joints (Superstructure elements)</Description>
</CheckListItem>
<CheckListItem>
<Sequence>160</Sequence>
<Description>Substructure drainage (Durability elements)</Description>
</CheckListItem>
<CheckListItem>
<Sequence>60</Sequence>
<Description>Parapet beam or cantilever (Superstructure elements)</Description>
</CheckListItem>
</CheckList>
</EamCheckListInfo>
</UserArea>
</MaintenanceOrderLine>
</MaintenanceOrder>
</DataArea>
</SyncMaintenanceOrder>
I need sample of an XSLT code for selecting only the text node described above.
I'm not sure I really get your question.
This will print the Description of the CheckListItem which has a Sequence of 40:
<xsl:value-of select="//CheckListItem/Sequence[text()='40']/../Description"/>
Try it here: https://xsltfiddle.liberty-development.net/ehVZvvZ
Try the below code
<xsl:value-of select="*[local-name(.)='SyncMaintenanceOrder']/*[local-name(.)='DataArea']/*[local-name(.)='MaintenanceOrder']/*[local-name(.)='MaintenanceOrderLine']/*[local-name(.)='UserArea']/*[local-name(.)='EamCheckListInfo']/*[local-name(.)='CheckList']/*[local-name(.)='CheckListItem']/*[local-name(.)='Sequence'][text() = '40']/../*[local-name(.)='Description']" />

In XSL how to check datatype of attribute given in schema

I have XML that contains date values where type given in schema is not xs:date but user defined simple type as date_type.
In resulting XML I wanted to change the format of date say from "YYYY-MM-DD" to "YYYYMMDD" for all attribues having type as date_type.
Below link says that there is way to do but I was not able to compile stylesheet using attribute(*,type)
http://www.ibm.com/developerworks/xml/library/x-schemaawarexslt/#table2
My XML is:
<input>
<car mileage="15000" mfgDate="2012-12-31"/>
<battery mfgDate="2012-03-01" expiryDate="2014-12-31"/>
...
</input>
In my Schema files I have data type date_type as:
<xsd:simpleType name="date_type">
<xsd:restriction base="xsd:string">
<xsd:length value="8"/>
</xsd:restriction>
</xsd:simpleType>
Also mfgDate and expiryDate are of date_type as:
<xsd:attribute name="mfgDate" type="sch:date_type"/>
<xsd:attribute name="expiryDate" type="sch:date_type"/>
Expected output is:
<input>
<car mileage="15000" mfgDate="20121231"/>
<battery mfgDate="20120301" expiryDate="20141231"/>
...
</input>
Is there a way to check the data type of attribute for all such types and do the string manipulation like:
<xsl:template match="attribute(*,sch:date_type)">
<xsl:value-of select="translate(.,'-','')"/>
</xsl:template>
Above line attribute(*,sch:date_type) is giving syntax error TransformerConfigurationException: Could not compile stylesheet.

Remove Namespace from XML Output whilst using 1 XSLT

I am using Crystal Report 2011 Export using XSLT and cannot use the tag namespace-alias in the XSLT for some reason.
I have the following XSLT :-
<xsl:namespace-alias stylesheet-prefix="b" result-prefix="#default"/>
<xsl:template match="/b:CrystalReport">
<root>
<xsl:for-each select="b:Details">
<person>
<VRN><xsl:value-of select="b:Section/b:Field[#Name='ITMVEHICLEREGNUM1']/b:FormattedValue"/></VRN>
<Make><xsl:value-of select="b:Section/b:Field[#Name='ITMMANUDESC1']/b:FormattedValue"/></Make>
<Model><xsl:value-of select="b:Section/b:Field[#Name='ITMODELDESC1']/b:FormattedValue"/></Model>
<PolicyNumber><xsl:value-of select="b:Section/b:Field[#Name='POLEXTERNAL11']/b:FormattedValue"/></PolicyNumber>
<Title><xsl:value-of select="b:Section/b:Field[#Name='TITDESCRIPTION1']/b:FormattedValue"/></Title>
<FirstName><xsl:value-of select="b:Section/b:Field[#Name='CLIFIRST1']/b:FormattedValue"/></FirstName>
<LastName><xsl:value-of select="b:Section/b:Field[#Name='CLISURN1']/b:FormattedValue"/></LastName>
<PostCode><xsl:value-of select="b:Section/b:Field[#Name='ADRPOSTCODE1']/b:FormattedValue"/></PostCode>
<CoverStartDate><xsl:value-of select="b:Section/b:Field[#Name='POLRENDATE1']/b:FormattedValue"/></CoverStartDate>
<CoverEndDate><xsl:value-of select="b:Section/b:Field[#Name='POLENDDATE1']/b:FormattedValue"/></CoverEndDate>
<FullyComp><xsl:value-of select="b:Section/b:Field[#Name='ITMCOVERTYPECDE1']/b:FormattedValue"/></FullyComp>
<GlassLimit>500</GlassLimit>
<GlassExcess>75</GlassExcess>
<VatReg><xsl:value-of select="b:Section/b:Field[#Name='CLIVATREG1']/b:FormattedValue"/></VatReg>
<AccidentDamageExecess>N/A</AccidentDamageExecess>
<RepairExcess>0.00</RepairExcess>
<Insurer><xsl:value-of select="b:Section/b:Field[#Name='INSNAME1']/b:FormattedValue"/></Insurer>
<Referral><xsl:value-of select="b:Section/b:Field[#Name='CENDESC1']/b:FormattedValue"/></Referral>
</person>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
The output looks like :-
<root xmlns:b="urn:crystal-reports:schemas:report-detail">
<person>
<VRN>XXXXXX</VRN>
<Make>AUSTIN</Make>
<Model>A35</Model>
<PolicyNumber>XXXXXXXX</PolicyNumber>
<Title>Mr</Title>
<FirstName>Gareth</FirstName>
<LastName>Jones</LastName>
<PostCode>AL23 6TR</PostCode>
<CoverStartDate>06.04.2011</CoverStartDate>
<CoverEndDate>05.04.2012</CoverEndDate>
<FullyComp>01</FullyComp>
<GlassLimit>500</GlassLimit>
<GlassExcess>75</GlassExcess>
<VatReg></VatReg>
<AccidentDamageExecess>N/A</AccidentDamageExecess>
<RepairExcess>0.00</RepairExcess>
<Insurer>My Insurer</Insurer>
<Referral>Direct</Referral>
</person>
</root>
I need to be able to remove the namespace from the tag and can only use 1 XSLT to do it.
Any help appreciated.
Thanks
Craig
You don't need to use namespace-alias here. The result is already in the null namespace, but if you want to suppress the b namespace declaration, you just need to use exclude-result-prefixes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:b="urn:crystal-reports:schemas:report-detail"
exclude-result-prefixes="b">

how to add root node tag in a XML document with XSLT

Iam parsing the xml document in SSIS through the xmlsource. It does not have any root tag. So iam trying to add the root tag to my xml document through XSLT, but getting the error as
[XML Task] Error: An error occurred with the following error message: "There are multiple root elements. Line 11, position 2.".
what is the XSL to be used to add the root element.? Please help..this is very urgent..
Please find the xml source below
<organizational_unit>
<box_id>898</box_id>
<hierarchy_id>22</hierarchy_id>
<parent_box_id>0</parent_box_id>
<code>Team</code>
<description />
<name>CAPS Teams</name>
<manager_title />
<level>0</level>
</organizational_unit>
<organizational_unit>
<box_id>967</box_id>
<hierarchy_id>31</hierarchy_id>
<parent_box_id>0</parent_box_id>
<code>main</code>
<description />
<name>Protegent</name>
<manager_title />
<level>0</level>
<organizational_unit>
<box_id>968</box_id>
<hierarchy_id>31</hierarchy_id>
<parent_box_id>967</parent_box_id>
<code>19L</code>
<description>19L</description>
<name>19L</name>
<level>1</level>
<managers>
<manager>
<hierarchy_mgr_id>243</hierarchy_mgr_id>
<hierarchy_id>31</hierarchy_id>
<box_id>968</box_id>
<rep_id>19499</rep_id>
<unique_rep_id>100613948</unique_rep_id>
<first_name>Ed</first_name>
<last_name>Kill</last_name>
</manager>
</managers>
</organizational_unit>
<organizational_unit>
<box_id>1152</box_id>
<hierarchy_id>31</hierarchy_id>
<parent_box_id>967</parent_box_id>
<code>UNKNOWN_m</code>
<description>Unknown Reps</description>
<name>Unknown Reps</name>
<level>1</level>
</organizational_unit>
</organizational_unit>
Well which XSLT processor do you use, how do you use it? I usually don't suggest to use string processing to construct XML but if you have a fragment without a root element then perhaps doing string concatenation "<root>" + fragment + "</root>" is the easiest way to get a well-formed document. XSLT can work with fragments but how you do that depends on the XSLT processor or XML parser you use, for instance .NET can use an XmlReader with XmlReaderSettings with ConformanceLevel set to fragment, which can then be loaded in an XPathDocument (for processing with XSLT 1.0 and XslCompiledTransform) and probably also with Saxon's XdmNode (although I am not sure I remember that correctly).
The stylesheet would then simply do
<xsl:template match="/">
<root>
<xsl:copy-of select="node()"/>
</root>
</xsl:template>
to wrap all top level nodes into a root element.