Can this XML be represented in CSV - Objective C - objective-c

I have following structure of an XML can we convert this into a CSV(ideally for Objective-C)
<root>
<Parent>
<Name>somename</Name>
<Age>20</Age>
<Child>
<ChildItem1>somevalue</ChildItem1>
<ChildItem2>somevalue</ChildItem2>
</Child>
<Child>
<ChildItem1>somevalue</ChildItem1>
<ChildItem2>somevalue</ChildItem2>
</Child>
</Parent>
<Parent>
<Name>somename</Name>
<Age>20</Age>
<Child>
<ChildItem1>somevalue</ChildItem1>
<ChildItem2>somevalue</ChildItem2>
</Child>
<Child>
<ChildItem1>somevalue</ChildItem1>
<ChildItem2>somevalue</ChildItem2>
</Child>
</Parent>
</root>
The problem i am facing is with the List formation of the nodes.
Thanks in advance
Edited : My Problem is i need to get the XML above as a result of CSV/Excel spread sheet, but dont know how to create such a format of cells in it.

CSV describes a grid of data.
XML describes a tree of data.
The only XML that could be directly converted to CSV is one with a root node, containing one or more elements of the same type, each of which contained the same number and types of elements as children.
This XML doesn't fit that criteria, so you would need to come up with explicit rules to convert the data structure to CSV and back. If every parent element contains exactly two child elements (which is unlikely in real data, but holds for the example) then you could just flatten the children.

Related

Many to one mapping in Mule

Example I have an input xml,
<root>
<first>
<a>2</a>
</first>
<first>
<a>3</a>
</first>
<first>
<a>4</a>
</first>
</root>
That should be mapped to,
<root>
<a>2</a>
<a>3</>
<a>4</a>
</root>
I already have output xsd defined that is derived from second xml above but I don't see the mapping in my target because it is one level.
First xml has 3 level and second one is 2 level. So I could not map the child element mapping.
Look at the Branch tangs in the attached image.
You just need to set a mapping where for each input.first -> for each input.a create a output.a.
This is doine using the element mapping controls at the top center (over the lines).

Why replace one attribute by element is valid, and two attributes not?

In a identity transform we can delete an attribute by
<xsl:template match="#myAttrib"/>
this works for any input... And we can "replace" the attribute by an element with
<xsl:template match="#myAttrib"><b>my new element</b></xsl:template>
... but it works only when input have only one attribute.
By other hand, if I need to replace attribute's value, the xsl:template behaviour is the same, that is,
<xsl:template match="#myAttrib">newValue</xsl:template>
not replaces the value, but delete attribute and include the "newValue" as a textNode.
Why "replace value" is invalid?
Why "replace by element" is not an error?
Why "replace by element" in a "two attributes (per element) context" is an error?
EDIT (for explain "two attributes"), suppose the input
<root>
<parent myAttrib1="1" myAttrib2="2">
<child myAttrib="1" myAttrib3="1"/>
</parent>
<sibling myAttrib0="1"/>
</root>
only the element sibling have one attribute.
It's difficult to answer your questions because some of your assumptions are wrong. For example:
<xsl:template match="#myAttrib"><b>my new element</b></xsl:template>
works for any number of elements. When applied (together with an identity transform template) to the following input:
<root>
<parent myAttrib="1">
<child myAttrib="1"/>
</parent>
<sibling myAttrib="1"/>
</root>
the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<parent>
<b>my new element</b>
<child>
<b>my new element</b>
</child>
</parent>
<sibling>
<b>my new element</b>
</sibling>
</root>
So clearly your assertion that "it works only when input have only one element" is not true.
With regard to:
<xsl:template match="#myAttrib">newValue</xsl:template>
This does not replace the value of myAttrib because the template matches the attribute - not its value (as an aside: the value of an attribute is not a node and cannot be matched). So just like before, the attribute is matched and another node is output in its place; first it was an element, now it's a text node. That's the only difference.
Edit:
The "replace procedure" is one attribute-node per one element-node.
No, that's not true either. Consider, for example, the following input:
<root>
<parent red="1" green="2">
<child red="1" blue="1"/>
</parent>
<sibling green="1" blue="1"/>
</root>
and the following template:
<xsl:template match="#red | #blue">
<new/>
</xsl:template>
or:
<xsl:template match="#*[contains(name(), 'r')]">
<new/>
</xsl:template>
--
BTW, none of these examples will work with Saxon - but that's another story.
Why "replace value" is invalid?
An XSLT template replaces one thing with another thing. In this case, you are replacing an attribute with a text node. If you want to replace an attribute with another attribute of the same name, but different content, you can do this:
<xsl:template match="#myAttrib">
<xsl:attribute name="{name()}">newValue</xsl:attribute>
</xsl:template>
Why "replace by element" is not an error?
See above. An XSLT template substitutes one thing for another.
Why "replace by element" in a "two attributes (per element) context" is an error?
This can cause an error in certain situations. It is not automatically an error.
XSLT does not allow adding attributes to a parent element in the output stream after other node types have already been added. Presumably, what is happening in your case is:
You are substituting myAttrib1 with an element.
You have an identity template copying myAttrib2 as a new attribute.
If myAttrib2 gets processed after myAttrib1, then an error will occur. (There is no guarantee on the order in which attributes will be processed).
This can be tricky to fix, but here is one approach that will work in certain cases:
<xsl:template match="#*[../#myAttrib]" />
<xsl:template match="#myAttrib">
<xsl:copy-of select="../#*[(. | current())[2]]" />
<b>my new element</b>
</xsl:template>
Translating to another readers what I understand from Michael's answer (#michael.hor257k) and my comments there; thanks Michael!
Assume you have an input XML,
<root>
<parent A="1" B="2">
<child C="1" D="1" E="0"/>
</parent>
<sibling E="1">text1</sibling>
</root>
Here's a diagram of the internal DOM representation, that is a tree:
root
/ \
parent sibling
/ \ \ \
(A,B) child (E) [text1]
\
(C,D,E)
The element root is a node, the element parent is a node, the attribute #A is a node, etc. Text also is a node... But not all the tree-itens are nodes: some itens in the diagram are into parenthesis, because they are collections of attribute-nodes.
In the diagram, the collection is a tree-item, the attribute not. We can imagine procedures to delete or replace items of the tree.
The "Delete node" task works with any individual node, pointed by its XPath.
We can imagine "Delete item" task as well (see diagram), and point the item by a XPath.
To delete a collection-item, the XPath must to point all the nodes of the collection, so parent/#* poits an item, but parent/#A not (because ramains parent/#B). XPath sibling/#E points a collection because sibling element have only one attribute. XPath #E points two nodes, one characterizing a collection, other not.
The task "Replace item X by text" or "Replace item X by element", need a XPath pointing the item X. Only tree-itens can be replaced. To replace a collection-item, the XPath must to point all the nodes of the collection.
Summarizing: the collection of attributes is the item, not the attribute-node; this is the point (!), and where confusion arises.
In DOM representation we can access nodeValue property, for both, elements and attributes, and we can change it in both cases: this is other source of confusion, because this concept of "change the nodeValue property" not exists in XSLT.
So,
Why "replace value" is invalid?
An XPath sibling/#E points to the a node attribute E. We need something like sibling/#E/nodeValue() to point the value and replace it, but this kind of XPath not exist.
(edit) IMPORTANT: as showed in this question, we can to change an attribute value in a ID-transform, by the use of xsl:attribute, see #JLRishe's answer in this page.
Why "replace by element" is not an error?
The concept is "replace an item by other item". Make sense when we see the diagram o the "tree of items".
Is wrong to imagine "replace a node by element" because is wrong to imagine a "tree of nodes", and a generic XPath node can be an attribute of a collection with more than one members.
Why "replace by element" in a "two attributes (per element) context" is an error?
Because the XPath of an individual attribute of a collection with more than one attributes, not represents the collection. The XPath must to point all attributes of the collection, to be used in a replace procedure.

xslt 1.0 select first n elements whose child element is one of allowed values

I have one xml, and I have to find first n element whose child element has one of allowed value
e.g. for following xml, I want to select element whose state is WA or NY. List of allowed state is dynamic value so I can't use
<xsl:apply-templates select="element[(state='WA' or state='NY')]"/>
when I am trying to filter it with contains, nothing is happening. e.g.
<xsl:variable name="allowedListPadded">;WA;NY;</xsl:variable>
<xslt:apply-templates select="element[contains($allowedListPadded,concat(';',state,';'))]"/>
XML:
<items>
<element>
<state>WA</state>
<title>Washington</title>
</element>
<element>
<state>OR</state>
<title>Oragon</title>
</element>
<element>
<state>NY</state>
<title>New York</title>
</element>
<element>
<state>WA</state>
<title>Washington News</title>
</element>
<element>
<state>TX</state>
<title>Texas</title>
</element>
</items>
I was thinking to filter elements in apply-templates and then in template, wants to use position() < n. However got stuck with first part only.
complete xslt as asked.
<xslt:stylesheet version="1.0" xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xslt">
<xslt:output omit-xml-declaration="yes" method="xml" />
<xslt:template match="root">
<xslt:text>{"statelist":</xslt:text>
<xslt:choose>
<xslt:when test="$allowedListPadded=''">
<!-- if no list is present, give default state -->
<xslt:apply-templates select="element[state = 'WA']"/>
</xslt:when>
<xslt:otherwise>
<xslt:apply-templates select="element[contains(allowedListPadded,concat(';',state,';'))]"/>
</xslt:otherwise>
</xslt:choose>
<xslt:text>}</xslt:text>
</xslt:template>
</xslt:stylesheet>
<xslt:apply-templates select="element[contains(allowedListPadded,concat(';',state,';'))][position() < 5]"/>
The trick here is not using an and operator in your predicate, but to use two predicates. The first one creates a node-set including the selected elements, and the second one returns a node-set with 5 (for example) elements of this node-set.
You are matching root element and there isn't any root element in your xml. You must change that and match items element. Your approach:
<xslt:variable name="allowedListPadded">;WA;NY;</xslt:variable>
<xslt:apply-templates select="element[contains($allowedListPadded,concat(';',state,';'))]"/>
should work then.

Not able to get desired output while generating xml files from SQL query from SQL Server

I am executing this query
select category "ROOT/category",
question "Category/question",
option1 "Category/option1"
from testDB2 for XML PATH ('ROOT') , ELEMENTS
Presently the database has three entries and the xml file i get is this
<ROOT>
<ROOT>
<category>maths</category>
</ROOT>
<Category>
<question>2+2?</question>
<option1>1</option1>
</Category>
</ROOT>
<ROOT>
<ROOT>
<category>maths</category>
</ROOT>
<Category>
<question>100*0</question>
<option1>0</option1>
</Category>
</ROOT>
<ROOT>
<ROOT>
<category>chemistry</category>
</ROOT>
<Category>
<question>H2O?</question>
<option1>water </option1>
</Category>
</ROOT>
I do not want this, i want a file with just one main Parent node and rest of them as its child and each child can be parent for other child nodes, but there should be just one single main Parent node, in this case each row is a separate parent and there is no main or single parent
I hope I am able to tell my question properly. Thanks
try something like this:
select category,
question,
option1
from testdb2
for xml raw('Category'), elements, root('Categories')
for xml raw: this will make a node for each row in your table, with every column an attribute for that node
for xml raw('user'): this is the same as xml raw, but you specify the name of the nodes
for xml raw('user') elements: you swith from a attribute view to a node view. every column will be a node in your row node
root('Users'): you can use this to name your parent root
hope this helps
I think you want to use the FOR XML AUTO mode to shape your output.
Not 100% sure what it is you really want, but how about this:
SELECT
category '#Name',
question "Category/question",
option1 "Category/option1"
FROM
dbo.testDB2
FOR XML PATH('Category'), ROOT('ROOT')
Does that get closer to what you want? If I'm not mistaken (can't test right now), this should give you something like:
<ROOT>
<Category Name="maths">
<question>100*0</question>
<option1>0</option1>
</Category>
<Category Name="chemistry">
<question>H2O?</question>
<option1>water </option1>
</Category>
</ROOT>
If not - could you post a few sample rows of data, and what you expect to get from your SELECT in the end??
Marc

Import Xml nodes as Xml column with SSIS

I'm trying to use the Xml Source to shred an XML source file however I do not want the entire document shredded into tables. Rather I want to import the xml Nodes into rows of Xml.
a simplified example would be to import the document below into a table called "people" with a column called "person" of type "xml". When looking at the XmlSource --- it seem that it suited to shredding the source xml, into multiple records --- not quite what I'm looking for.
Any suggestions?
<people>
<person>
<name>
<first>Fred</first>
<last>Flintstone</last>
</name>
<address>
<line1>123 Bedrock Way</line>
<city>Drumheller</city>
</address>
</person>
<person>
<!-- more of the same -->
</person>
</people>
I didn't think that SSIS 2005 supported the XML datatype at all. I suppose it "supports" it as DT_NTEXT.
In any case, you can't use the XML Source for this purpose. You would have to write your own. That's not actually as hard as it sounds. Base it on the examples in Books Online. The processing would consist of moving to the first child node, then calling XmlReader.ReadSubTree to return a new XmlReader over just the next <person/> element. Then use your favorite XML API to read the entire <person/>, convert the resulting XML to a string, and pass it along down the pipeline. Repeat for all <person/> nodes.
Could you perhaps change your xml output so that the content of person is seen as a string? Use escape chars for the <>.
You could use a script task to parse it as well, I'd imagine.