SimpleXML save tag content as variable - variables

OK I've been working with tag attributes up to now, but what if I want to save the actual contents of a tag as a variable, how would I do that?
For instance, in the example below, how would I save 'John' to a variable?
<person>
<name>John</name>
</person>
Thanks!

You're talking about SimpleXML in PHP?
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><person><name>John</name></person>');
$john = $xml->name ;
echo $john ;
The reason we use $xml->name in our example rather than $xml->person->name is that SimpleXML will assume the root element (worth keeping in mind :). In a real example the XML would have a different root element, with perhaps several <person> elements, which you then could get by array notation, as in ;
$james = $xml->person[4]->name ;
A more powerful way is to use Xpath which is worth looking into for better dealing with complex XML ;
$john = $xml->xpath ( 'person/name' ) ;

Using PHP, you can do it in this way:-
<?php
$xmlstr = <<<XML
<person>
<name>John</name>
</person>
XML;
$xml = new SimpleXMLElement($xmlstr);
$name_person = $xml->name;
// If you are unsure about the node string, then it's best to write it as:-
$name_person = $xml->{'name'};
/**
* This above statement will take care if the node string contain characters not permitted under PHP's naming convention (e.g. the hyphen) can be accomplished by encapsulating the element name within braces and the apostrophe.
*/
?>
More info is available here.
Hope it helps.

Related

How to create a message containing xml prolog declaration

I am trying to create some dynamic xml messages which will be sent to a service which expects xml. Said service also needs the xml prolog to be specified.
As I want to do a lot of manipulation on the xml I am reading it in a native xml type, however it seems that karate loses the xml prolog information during the conversion (on 0.9.5 and 0.9.6.RC3)
Feature: Example
# https://www.w3.org/TR/xml/#sec-prolog-dtd
Scenario: Example
Given def nativeXML =
"""
<?xml version="1.0" encoding="UTF-8" ?>
<greeting>Hello world</greeting>
"""
When string nativeToString = nativeXML
* print nativeToString
Then assert nativeToString.contains("encoding")
Is there a way to preserve the xml prolog?
Code to reproduce this can be found here: https://github.com/KostasKgr/karate-issues/blob/xml_prolog_to_string/src/test/java/examples/example.feature
Kind regards
Right now there is no other way but to append it manually, which IMO is simple enough. Karate removes it by default during a string conversion, because it gets in the way during Node operations.
Given def temp =
"""
<?xml version="1.0" encoding="UTF-8" ?>
<greeting>Hello world</greeting>
"""
* string body = temp
* def body = '<?xml version="1.0" encoding="UTF-8" ?>' + body
* print body
Then assert body.contains("encoding")

Replacing XML node key using dataprovider karate

I am reading my xml structure from a file and replacing the values from the examples
def inputXml = read('classpath:xml/input.xml')
My xml structure is like below
<input>
<data>
<props>
<p n="AMOUNT">1000</p>
<p n="NAME">name</p>
<p n="{ACCOUNTTYPE}">purpose</p>
</props>
</data>
</input>
I am driving data from examples and setting/replacing the input xml as below
* set inputXml/input/data/props/p[#n='AMOUNT'] = <AMOUNT> -- Works fine
* set inputXml/input/data/props/p[#n='NAME'] = <NAME> -- Works fine
Examples:
|AMOUNT|NAME|ACCOUNTTYPE|PURPOSE|
|100|abc|BUSINESS|smallbusiness|
|2000|def|PERSONAL|home|
I want to update the "n" tag name ACCOUNTTYPE and corresponsding PURPOSE similar to above(both key and value). Is there a way to achieve this in Karate? Please suggest.
Is is possible to use '#(accountType)' and '#(purpose)' inside the xml file similar to json and run?
Is is possible to use '#(accountType)' and '#(purpose)' inside the xml file
Yes. Please read the docs: https://github.com/intuit/karate#embedded-expressions
And the examples: xml.feature
Given def user = <user><name>john</name></user>
And def lang = 'en'
When def session = <session><locale>#(lang)</locale><sessionUser>#(user)</sessionUser></session>

Edit XML tag by attribute

I have a XML document which looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
<Data key="dailyKey">19283</Data>
</Configuration>
And in my vb.net program I want to change the value from "<Data>" by the attribute "dailyKey"
I have tried to understand myself on this but cannot figure out how to edit TAG by ATTRIBUTE
Please help, Richard
You could use XPath expressions and the SelectSingleNode method like this:
Dim node = xmlDoc.SelectSingleNode("//data[#key=""dailyKey""]")
Then you can modify the value of node as you wish to. You can find more XPath examples at MSDN.
The workflow in its entirety would be:
1. Load the XML Document for manipulation
You can use the XmlDocument class to load (and subsequently save) your XML Document like this:
Dim xmlDoc As New XmlDocument()
xmlDoc.Load("<Here goes your url // You can also feed in a stream to this method>")
2. Locate the node you want to modify
As mentioned earlier, use the SelectSingleNode function to locate the node you are trying to modify the value of. It takes an XPath expression.
Dim node = xmlDoc.SelectSingleNode("//data[#key=""dailyKey""]")
3. Modify the node
You can now edit the node (tag) in whatever way you wish. It seems you want to edit the contained value. Do it by changing the Value property of the XmlNode:
node.Value = 224062 'Random value. Change to suit your needs.
4. Save the XML Document (Obviously :P)
xmlDoc.Save()

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.

xml parsing in iPhone and getting other tags with same names

Let me try to explain as clear as possible what I mean exactly with this question.
The xml looks instead like this
<Books>
<Book id="1">
<title>Circumference</title>
<author>Nicholas Nicastro</author>
<summary>Eratosthenes and the Ancient Quest to Measure the Globe.</summary>
</Book>
<Book id="2">
<title>Copernicus Secret</title>
<author>Jack Repcheck</author>
<summary>How the scientific revolution began</summary>
</Book>
</Books>
It will look like this
<Books>
<Book id="1">
<title>Circumference</title>
<author>Nicholas Nicastro</author>
<summary id ='1'>Eratosthenes and the Ancient Quest to Measure the Globe.</summary>
<summary id ='2'>Eratosthenes more info in another tag.</summary>
<summary id ='3'>Eratosthenes and again another tag.</summary>
<summary id ='4'>Eratosthenes and the final tag another one here</summary>
</Book>
<Book id="2">
<title>Copernicus Secret</title>
<author>Jack Repcheck</author>
<summary id ='1'>How the scientific revolution began</summary>
<summary id ='2'>Eratosthenes more info in another tag.</summary>
<summary id ='3'>Eratosthenes and again another tag.</summary>
<summary id ='4'>Eratosthenes and the final tag another one here</summary>
</Book>
</Books>
Now if I follow the instruction on the site listed above , it doesn't explain how to handle summary 2,3,4( the xml i need to parse looks like that) and how I can show their output. All I will get is the last line. Does anyone have an idea about how I can get the other ones as well( meaning 2,3 in this case it seems to show only the last one since that's probably the last in the currentElementValue ).
I'm a bit confused would I have to address the attribute here as well or should I create a new search tag in my parser?
I think this is what you need to be looking at, you could grab the value of the id field from the attributes and using that value assign it to a variable which you can then use.
So I might have something this in my didStartElement (where attributes is a variable declared in the header):
if([elementName isEqualToString:#"Summary"]){
attributes = attributeDict;
}
Then something like this in my foundCharacters:
if([[attributes valueForKey:#"id"] intValue] == 1){
doSomething
}else if([[attributes valueForKey:#"id"] intValue] == 2){
doSomethingElse
}...
and so on until you've got all your data out.
N.B. This is 100% untested code but I'm confident it might work...
You will need to keep track of the summary elements you have parsed so far by keeping all the values in some container like an array: NSMutableArray. Thus, instead of an NSString to keep the summary, you'd have an NSMutableArray to hold the list of summaries you have parsed.
Whenever you encounter a summary in your parser, you don't set the NSString summary to the string you just read (which replaces the old value and explains why you only get the last summary tag). Instead, you store it as a new string and add that string to your NSMutableArray.
The problem with the design in the blog post you linked to is that it uses keyValueCoding to set the properties in the Book object and that doesn't facilitate adding items to an array item very well. Hence, you will need to include some special handling for the summary element in the parser and add methods to the Book class that allow you to add items to the summary array. See this post on how to also do that with KVC.