I want to include an xml document with arbitrary user provided data in another one using nokogiri.
I have tried Node#add_child and encountered a problem: nokogiri looses namespace definition if there is a uri in child_doc that is also present in main doc but with a different prefix.
Example:
doc = Nokogiri::XML %(
<s:rack xmlns:s="urn://shelf">
<s:shelf></s:shelf>
</s:rack>
)
child_doc = Nokogiri::XML %(
<m:shelf xmlns:m="urn://shelf">
<m:book></m:book>
</m:shelf>
)
doc.root.add_child(child_doc.root)
doc.to_xml
# =>
# <s:rack xmlns:s="urn://shelf">
# <s:shelf/>
# <!-- namespace for prefix m is not declared! -->
# <m:shelf>
# <m:book/>
# </m:shelf>
# </s:rack>
Namespace for prefix m is lost.
Here is the resulting doc object, pretty printed:
#(Document:0x1b2ce28 {
name = "document",
children = [
#(Element:0x1b327c4 {
name = "rack",
namespace = #(Namespace:0x1b320a8 { prefix = "s", href = "urn://shelf" }),
children = [
#(Text "\n "),
#(Element:0x1b45f90 { name = "shelf", namespace = #(Namespace:0x1b320a8 { prefix = "s", href = "urn://shelf" }) }),
#(Text "\n "),
#(Element:0x1a9e5d8 {
name = "shelf",
namespace = #(Namespace:0x1a87450 { prefix = "m", href = "urn://shelf" }),
children = [
#(Text "\n "),
#(Element:0x1a41dec { name = "book", namespace = #(Namespace:0x1a87450 { prefix = "m", href = "urn://shelf" }) }),
#(Text "\n ")]
})]
})]
})
As you can see internally namespaces in added nodes are correct but they are serialized wrong. How do I get nokogiri to save them in the resulting xml?
Related
I currently have the below lists,
local.security_list =
[
{
ocid = security_list_id_1
name = subnet1
},
{
ocid = security_list_id_2
name = subnet1
},
{
ocid = security_list_id_3
name = subnet2
},
{
name = subnet2
ocid = security_list_id_4
},
]
var.vcn_security_lists = [
{
security_list_name = security_list_1
subnet_name = subnet1
},
{
security_list_name = security_list_2
subnet_name = subnet1
},
{
security_list_name = security_list_3
subnet_name = subnet2
}
]
I want to create the security lists using the var.vcn_security_lists list and then assign them to the subnet later on by using the subnet_name field. I have done this previously using the index() function as below, which loops through a subnet and pulls out the security list with the same subnet name. The problem is that this only returns one item - how can I return multiple from a list ?
subnet_security_list_ocid = [local.security_list[index(local.security_list.*.name,var.vcn_security_lists[index(var.vcn_security_lists.*.subnet_name,var.vcn_subnets[count.index].subnet_name)].security_list_name)].id]
I have a configurable value of a table fetch function which i get as an input string. I need that string to be executed as a code and fetch a value from the nested table.
I tried using load(string), its not working
local function main()
local t = {
["name1"] = "value1",
["name2"] = {["name1"] = "value1",
["name2"] = { 1, false, true, 23.54, "a \021 string" },
name3 = nil
},
name3 = nil
}
local string = 't.name2.name1'
print(type(string))
print(load(string))
end
print(load(string)) should print value1.
Below code works
local function main()
t = {
["name1"] = "value1",
["name2"] = {["name1"] = "value1",
["name2"] = { 1, false, true, 23.54, "a \021 string" },
name3 = nil
},
name3 = nil
}
string = "t.name2.name1"
print(type(string))
val = load("return "..string)()
print(val)
end
Upon parsing an html table, I am able to get the first row of the table as a Nokogiri element.
2.2.1 :041 > pp content[1]; nil
#(Element:0x3feee917d1e0 {
name = "tr",
children = [
#(Element:0x3feee917cfd8 {
name = "td",
attributes = [
#(Attr:0x3feee917cf74 { name = "valign", value = "top" })],
children = [
#(Element:0x3feee917ca60 {
name = "a",
attributes = [
#(Attr:0x3feee917c9fc {
name = "href",
value = "/cgi-bin/own-disp?action=getowner&CIK=0001513362"
})],
children = [ #(Text "Maestri Luca")]
})]
}),
#(Text "\n"),
#(Element:0x3feee917c150 {
name = "td",
children = [
#(Element:0x3feee917d794 {
name = "a",
attributes = [
#(Attr:0x3feee9179fb8 {
name = "href",
value = "/cgi-bin/browse-edgar?action=getcompany&CIK=0001513362"
})],
children = [ #(Text "0001513362")]
})]
}),
#(Text "\n"),
#(Element:0x3feee91796a8 {
name = "td",
children = [ #(Text "2016-09-04")]
}),
#(Text "\n"),
#(Element:0x3feee9179194 {
name = "td",
children = [ #(Text "officer: Senior Vice President, CFO")]
}),
#(Text "\n")]
})
=> nil
This is the content from the row:
Maestri Luca 0001513362 2016-09-04 officer: Senior Vice President, CFO
I need to access the Name, Number, Date and Title from the Nokogiri element.
One way of doing it is as below:
2.2.1 :042 > pp content[1].text; nil
"Maestri Luca\n0001513362\n2016-09-04\nofficer: Senior Vice President, CFO\n"
However, I am looking for a way of accessing the elements individually, not as one long sting with newline characters. How can I do it?
name, number, date, title = *content[1].css('td').map(&:text)
if content[1] is a tr, content[1].css('td') will find all td elements beneath it, .map(&:text) will call td.text for each of those td and put it into an array, which we than splat with * so we can do multiple assignment.
(Note: next time, please include the original HTML fragment, not the Nokogiri node inspect result.)
I have the following class that I need to convert into a JSON String using Xcode 7 and above. In the previous version of Xcode there was a JSONSerelization.toJson(AnyObject) function available, however does not appear in Xcode7 .
I need to convert the following class :
struct ContactInfo
{
var contactDeviceType: String
var contactNumber: String
}
class Tradesmen
{
var type:String = ""
var name: String = ""
var companyName: String = ""
var contacts: [ContactInfo] = []
init(type:String, name:String, companyName:String, contacts [ContactInfo])
{
self.type = type
self.name = name
self.companyName = companyName
self.contacts = contacts
}
I Have set up my test data as follows
contactType =
[
ContactInfo(contactDeviceType: "Home", contactNumber: "(604) 555-1111"),
ContactInfo(contactDeviceType: "Cell", contactNumber: "(604) 555-2222"),
ContactInfo(contactDeviceType: "Work", contactNumber: "(604) 555-3333")
]
var tradesmen = Tradesmen(type: "Plumber", name: "Jim Jones", companyName: "Jim Jones Plumbing", contacts: contactType)
Any help or direction would be appreciated.
I do not think that there is any direct way, even in previous Xcode. You will need to write your own implementation. Something like below:
protocol JSONRepresenatble {
static func jsonArray(array : [Self]) -> String
var jsonRepresentation : String {get}
}
extension JSONRepresenatble {
static func jsonArray(array : [Self]) -> String {
return "[" + array.map {$0.jsonRepresentation}.joinWithSeparator(",") + "]"
}
}
And then implement JSONRepresentable in your modals like below:
struct ContactInfo: JSONRepresenatble {
var contactDeviceType: String
var contactNumber: String
var jsonRepresentation: String {
return "{\"contactDeviceType\": \"\(contactDeviceType)\", \"contactNumber\": \"\(contactNumber)\"}"
}
}
struct Tradesmen: JSONRepresenatble {
var type:String = ""
var name: String = ""
var companyName: String = ""
var contacts: [ContactInfo] = []
var jsonRepresentation: String {
return "{\"type\": \"\(type)\", \"name\": \"\(name)\", \"companyName\": \"\(companyName)\", \"contacts\": \(ContactInfo.jsonArray(contacts))}"
}
init(type:String, name:String, companyName:String, contacts: [ContactInfo]) {
self.type = type
self.name = name
self.companyName = companyName
self.contacts = contacts
}
}
Having a problem translating my json code form this dataObject...
var dataObject = {
"timeline":
{
"headline":"The Main Timeline Headline Goes here",
"type":"default",
"text":"<p>Intro body text goes here, some HTML is ok</p>",
"asset": {
"media":"http://yourdomain_or_socialmedialink_goes_here.jpg",
"credit":"Credit Name Goes Here",
"caption":"Caption text goes here"
},
"date": [
{
"startDate":"2011,12,10",
"endDate":"2011,12,11",
"headline":"Headline Goes Here",
"text":"<p>Body text goes here, some HTML is OK</p>",
"asset": {
"media":"http://twitter.com/ArjunaSoriano/status/164181156147900416",
"thumbnail":"optional-32x32px.jpg",
"credit":"Credit Name Goes Here",
"caption":"Caption text goes here"
}
}
],
"era": [
{
"startDate":"2011,12,10",
"endDate":"2011,12,11",
"headline":"Headline Goes Here",
"text":"<p>Body text goes here, some HTML is OK</p>",
}
]
}
}
into this method...
def timeline
t = {}
t['timeline'] = {}
t['timeline']['headline'] = "Lorem"
t['timeline']['text'] = "default"
t['timeline']['asset'] = {}
t['timeline']['asset']['media'] = ""
t['timeline']['asset']['credit'] = ""
t['timeline']['asset']['caption'] = ""
t['timeline']['date'] = [{}]
t['timeline']['date']['startDate'] = "2011,12,10"
t['timeline']['date']['endDate'] = "2011,12,11"
t['timeline']['date']['headline'] = ""
t['timeline']['date']['text'] = ""
t['timeline']['date']['asset'] = {}
t['timeline']['date']['asset']['media'] = ""
t['timeline']['date']['asset']['thumbnail'] = ""
t['timeline']['date']['asset']['credit'] = ""
t['timeline']['date']['asset']['caption'] = ""
t['timeline']['era'] = [{}]
t['timeline']['era']['startDate'] = "2011,12,10"
t['timeline']['era']['endDate'] = "2011,12,11"
t['timeline']['era']['headline'] = ""
t['timeline']['era']['text'] = ""
return t
end
specifically I'm uncertain about
t['timeline']['date'] = [{}]
and
t['timeline']['era'] = [{}]
How should I properly write those lines?
t['timeline']['date'] = [{}]
that should work just fine. Only you have to add attributes slightly different. Like this:
t['timeline']['date'][0]['startDate'] = "2011,12,10"
^^^
first element in the array
Just build a hash directly:
def timeline
{
"timeline" = {
"headline" = "Lorem",
"text" = "default",
"asset" = {}
},
"date" = [{
"startDate" = "2011,12,10",
"asset" = {
"media" = ""
}
}]
}
end
Saves a lot of typing, and will mentally map much more naturally to JSON.