How to find the last element - xpath

I am trying to find the IMD in the last Line element in my edifact file, using xpath in biztalk - orchestration.
This is my xpath:
LastLineName = xpath(Message_2,"/*[local-name()='EFACT_D96A_INVOIC' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006']/*[local-name()='LINLoop1' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006']/*[local-name()='IMD_2' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006']/*[local-name()='C273_2' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006']/*[local-name()='C27304' and namespace-uri()='']last()");
And this is my edifat-file:
UNB+UNOB:1+BTS-SENDER:ZZZ+RECEIVE-PARTNER:ZZZ+130418:1513+19++++0++0'
UNH+19+INVOIC:D:01B:UN:EAN010'
BGM+380+353795+9'
DTM+171:2013-04-18'
LIN+1++8886419315339:VN'
IMD+++:::Razer Sphex - Full retai'
QTY+47:10'
PRI+AAA:89'
LIN+3++8886419330028:VN'
IMD+++:::Razer Deathadder RESPAWN'
QTY+47:10'
PRI+AAA:347'
LIN+4++8886419330127:VN'
IMD+++:::Razer Abyssus Gaming Mou'
QTY+47:1'
PRI+AAA:242,6'
LIN+5++8886419330660:VN'
IMD+++:::Razer Imperator 2012 Exp'
QTY+47:2'
PRI+AAA:447,5'
LIN+6++8886419311454:VN'
IMD+++:::Razer Lycosa gaming keyb'
QTY+47:2'
PRI+AAA:511,5'
LIN+7++8886419311614:VN'
IMD+++:::Razer Arctosa Silver Key'
QTY+47:2'
PRI+AAA:312'
LIN+10++8886419340317:VN'
IMD+++:::Anansi (MMO Keyboard)'
QTY+47:1'
PRI+AAA:639'
LIN+11++8886419330509:VN'
IMD+++:::Razer Naga - Molten Edit'
QTY+47:2'
PRI+AAA:479,5'
LIN+12++8886419330981:VN'
IMD+++:::Razer Naga Hex MOBA/ Act'
QTY+47:1'
PRI+AAA:479,5'
LIN+13++8886419312277:VN'
IMD+++:::Razer Carcharias Gaming'
QTY+47:2'
PRI+AAA:479,5'
LIN+14++8886419312628:VN'
IMD+++:::Razer Electra headset'
QTY+47:4'
PRI+AAA:383,5'
UNS+S'
MOA+139:790'
UNT+50+19'
UNZ+1+19'
It returns:
has an invalid token

At the very end, you have
last()
Positional indexers must be enclosed in square brackets.
So simply make it:
[last()]

I solved it. Sorry Arran, you were totally right about [last()]. I just needed to put it in another place than suggested.
This is the solution:
/*[local-name()='EFACT_D96A_INVOIC' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006']/*[local-name()='LINLoop1' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006'][last()]/*[local-name()='IMD_2' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006']/*[local-name()='C273_2' and namespace-uri()='http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006']/*[local-name()='C27304' and namespace-uri()='']/text()

Related

Nokogiri - parsing multi-line `<link>` tag as link and text

I am using Nokogiri to parse an RSS feed for a podcast. I am trying to grab a particular piece of data containing a link to the episode, so I'm using Nokogiri to parse the XML response for the RSS feed.
The relevant bit is below:
<item>
<title>An awesome title!</title>
...
<link>
http://www.foobar.com/episodes/1
</link>
</item>
Nokogiri appears to be having a hard time grabbing the <link> tag though; I am able to get the <item> tag as a Nokogiri::Node object, and I can grab the title just fine with node.css('title').text, but when I try the same with node.css('link').text, I get a blank string.
I tried calling node.children.to_a to examine all of the children in this node, and I noticed something odd: the text inside the <link> tag is being parsed as a separate child:
[0] = {Nokogiri::XML::Element} <title>An awesome title!</title>\n
[1] = {Nokogiri::XML::Element} <link>
[2] = {Nokogiri::XML::Text} http://www.foobar.com/episodes/1\n
Is there a way I can help Nokogiri properly parse this multi-line tag so that I can grab the text inside?
UPDATE: Here is the exact code I'm executing when I run into the issue.
require 'open-uri'
doc = Nokogiri::HTML(open('https://rss.acast.com/abroadinjapan')) # Returns Nokogiri::HTML::Document
node = doc.css('//item').first # Returns Nokogiri::XML::Element
node.css('title').text # Returns "Abroad in Japan: Two weeks more in Japan!"
node.css('link').text # Returns ""
node.css('link').inner_text # Also returns "" - saw this elsewhere and thought I'd try it
node.children.to_a # Result, parsed by RubyMine for readability:
result = Array (14 elements)
[0] = {Nokogiri::XML::Element} <title>Abroad in Japan: Two weeks more in Japan!</title>\n
[1] = {Nokogiri::XML::Element} <subtitle>Chris and Pete return and they've planned out a very different route through Northern Japan.&nbsp;\n\n\nOur Google Map can be found here:&nbsp;\ngoo.gl/3t4t3q&nbsp;\n\n\nGet in touch:&nbsp;abroadinjapanpodcast#gmail.com&nbsp;\nMore Abr...</subtitle>
[2] = {Nokogiri::XML::Element} <summary></summary>
[3] = {Nokogiri::XML::Element} <guid ispermalink="false"></guid>
[4] = {Nokogiri::XML::Element} <pubdate>Wed, 16 May 2018 21:00:00 GMT</pubdate>
[5] = {Nokogiri::XML::Element} <duration>01:00:00</duration>
[6] = {Nokogiri::XML::Element} <keywords></keywords>
[7] = {Nokogiri::XML::Element} <explicit>no</explicit>
[8] = {Nokogiri::XML::Element} <episodetype>full</episodetype>
[9] = {Nokogiri::XML::Element} <image href="https://imagecdn.acast.com/image?h=1500&w=1500&source=https%3A%2F%2Fmediacdn.acast.com%2Fassets%2Fcb30d29f-7342-46f0-a649-12f1b4e601f7%2Fcover-image-jgyt2ecc-japan.jpg"></image>
[10] = {Nokogiri::XML::Element} <description>Chris and Pete return and they've planned out a very different route through Northern Japan. <p><br></p>\n<p>Our Google Map can be found here: </p>\n<p>goo.gl/3t4t3q </p>\n<p><br></p>\n<p>Get in touch: abroadinjapanpodcast#gmail.com </p>\n<p>More Abroad In Japan shows available below, do subscribe, rate and review us on iTunes, and please tell your friends! </p>\n<p><br></p>\n<p>http://www.radiostakhanov.com/abroadinjapan/</p>]]></description>
[11] = {Nokogiri::XML::Element} <link>
[12] = {Nokogiri::XML::Text} https://www.acast.com/abroadinjapan/abroadinjapan-twoweeksmoreinjapan-\n
[13] = {Nokogiri::XML::Element} <enclosure url="https://media.acast.com/abroadinjapan/abroadinjapan-twoweeksmoreinjapan-/media.mp3" length="28806528" type="audio/mpeg"></enclosure>
NOTE: One of the URLs above uses a URL shortener, which SO doesn't like, so I replaced it with foobar.com.
The fix is a lot simpler than you would think. An RSS feed is not valid HTML, but it works with XML:
doc = Nokogiri::XML(open('...'))
Ruby also has a module named RSS, which might be better suited for something like this:
require 'rss'
doc = RSS::Parser.parse(open('...'))
doc.items.first.link
=> "https://...."

trying to parse specific data using xpath

I have a small xml file that I'm trying to grab the away_team first and then the home_team second.
/game/team/statistics/#goals gives me the data I want but I need to reverse the order. So I'm trying to understand how to get the away_team goals first, followed by the home_team.
Below is the file
<game id="f24275a9-4f30-4a81-abdf-d16a9aeda087" status="closed" coverage="full" home_team="4416d559-0f24-11e2-8525-18a905767e44" away_team="44167db4-0f24-11e2-8525-18a905767e44" scheduled="2013-10-10T23:00:00+00:00" attendance="18210" start_time="2013-10-10T23:08:00+00:00" end_time="2013-10-11T01:32:00+00:00" clock="00:00" period="3" xmlns="http://feed.elasticstats.com/schema/hockey/game-v2.0.xsd">
<venue id="bd7b42fa-19bb-4b91-8615-214ccc3ff987" name="First Niagara Center" capacity="18690" address="One Seymour H. Knox III Plaza" city="Buffalo" state="NY" zip="14203" country="USA"/>
<team name="Sabres" market="Buffalo" id="4416d559-0f24-11e2-8525-18a905767e44" points="1">
<scoring>
<period number="1" sequence="1" points="1"/>
<period number="2" sequence="2" points="0"/>
<period number="3" sequence="3" points="0"/>
</scoring>
<statistics goals="1" assists="2" penalties="7" penalty_minutes="23" team_penalties="0" team_penalty_minutes="0" shots="27" blocked_att="14" missed_shots="8" hits="25" giveaways="5" takeaways="10" blocked_shots="7" faceoffs_won="22" faceoffs_lost="28" powerplays="1" faceoffs="50" faceoff_win_pct="44.0" shooting_pct="3.7" points="3">
<powerplay faceoffs_won="2" faceoffs_lost="0" shots="0" goals="0" missed_shots="1" assists="0" faceoff_win_pct="100.0" faceoffs="2"/>
<shorthanded faceoffs_won="3" faceoffs_lost="3" shots="1" goals="0" missed_shots="0" assists="0" faceoffs="6" faceoff_win_pct="50.0"/>
<evenstrength faceoff_win_pct="40.5" missed_shots="7" goals="1" faceoffs_won="17" shots="26" faceoffs="42" faceoffs_lost="25" assists="2"/>
<penalty shots="0" goals="0" missed_shots="0"/>
</statistics>
<shootout shots="0" missed_shots="0" goals="0" shots_against="0" goals_against="0" saves="0" saves_pct="0"/>
<goaltending shots_against="33" goals_against="4" saves="29" saves_pct="0.879" total_shots_against="33" total_goals_against="4">
<powerplay shots_against="0" goals_against="0" saves="0" saves_pct="0"/>
<shorthanded shots_against="7" goals_against="0" saves="7" saves_pct="1.0"/>
<evenstrength goals_against="4" saves_pct="0.846" shots_against="26" saves="22"/>
<penalty shots_against="0" goals_against="0" saves="0" saves_pct="0"/>
<emptynet goals_against="0" shots_against="0">
<powerplay goals_against="0"/>
<shorthanded goals_against="0"/>
<evenstrength goals_against="0"/>
</emptynet>
</goaltending>
Here's an XPath 2.0 expression that should do what you asked, yielding a sequence of two elements:
(/game/team[#id = /game/#home_team]/statistics/#goals,
/game/team[#id = /game/#away_team]/statistics/#goals)
Credit to #Ian for sleuthing out the details of the question.
In XPath 1.0, you could concatenate string data from the two teams in whatever order you want:
concat(/game/team[#id = /game/#home_team]/statistics/#goals, ' ',
/game/team[#id = /game/#away_team]/statistics/#goals)
But as Ian said, you can't produce a nodeset with an order different from document order. (I don't think a nodeset has any intrinsic order at all... it's how it's processed that imposes an order.)
Update:
As Ian pointed out, your XML data is in a namespace, thanks to the default namespace declaration on <game>. Since you said that "/game/team/statistics/#goals gives me the data", I'm assuming that you've already taken care of this aspect of the problem, perhaps by declaring the default namespace in your XPath execution environment.

CSV to XML conversion using MFL

I have an CSV file like:
1234|abc|val1=12;val2=13;val3=14
1235|xyz|val1=15;val2=16;val3=18
I need to convert it into XML using mfl file.
This is my approach:
<StructFormat name='player' delimOptional='n' repeat='*'>
<FieldFormat name='FieldID' type='String' delimRef='' delim='|' dataDelim='"' delimOptional='n' optional='n' codepage='UTF-8'/>
<FieldFormat name='playerName' type='String' delimRef='' delim='|' dataDelim='"' delimOptional='n' optional='n' codepage='UTF-8'/>
<StructFormat name='extraList' delim='|' delimOptional='n' optional='y'>
<FieldFormat name='extra' type='String' delimRef='' delim='|' delimOptional='n' optional='y' codepage='UTF-8' repeat='*'/>
</StructFormat>
</StructFormat>
I don't know how to implement unlimited amount of couples: val1=12 assigned to each player.
Any help? Thank you!
Appears to be generated by tool, check used wizard for
Group Occurrence -> Repeat Delimiter -> Select this option to indicate that the group will repeat until the specified delimiter is encountered.
as per http://docs.oracle.com/cd/E13214_01/wli/docs70/diuser/fmtdef.htm - dated but still ok

Extract fields out of a ruby hash with special chars

I'm working to turn a pdf signature visible, using origami.pdf, and meanwhile I noticed that my signature is an hash, and so I try to capture fields like "Location", "Reason", "Date", "ContactInfo".
{/Type=>/Sig, /Contents=>"0\x82\a\xAE\x06\t*\x86H\x86\xF7\r\x01\a\x02\xA0\x82\a\
x9F0\x82\a\x9B\x02\x01\x011\v0\t\x06\x05+\x0E\x03\x02\x1A\x05\x000#\x06\t*\x86H\
x86\xF7\r\x01\a\x01\xA0\x16\x04\x14\xEF8uEn1#\x11M\x95\xE4\xD7\x9C\xFE(\xCF\xB7\
x92\x01\xC2\xA0\x82\x05\x970\x82\x05\x930\x82\x04{\xA0\x03\x02\x01\x02\x02\x04Bo
\x93\x8C0\r\x06\t*\x86H\x86\xF7\r\x01\x01\x05\x05\x000>1\v0\t\x06\x03U\x04\x06\x
13\x02pt1\x150\x13\x06\x03U\x04\n\x13\fMULTICERT-CA1\x180\x16\x06\x03U\x04\x03\x
13\x0FMULTICERT-CA 020\x1E\x17\r130320170147Z\x17\r140320164736Z0\x81\xA51\v0\t\
x06\x03U\x04\x06\x13\x02PT1\x150\x13\x06\x03U\x04\n\x13\fMULTICERT-CA1\x160\x14\
x06\x03U\x04\v\x13\rCERTIPOR - RA1\x120\x10\x06\x03U\x04\v\x13\tCorporate1 0\x1E
\x06\x03U\x04\v\x13\x17ESCRITA INTELIGENTE LDA1\x180\x16\x06\x03U\x04\v\x13\x0FW
eb Application1\x170\x15\x06\x03U\x04\x03\x13\x0ERECIBOS ONLINE0\x81\x9F0\r\x06\
t*\x86H\x86\xF7\r\x01\x01\x01\x05\x00\x03\x81\x8D\x000\x81\x89\x02\x81\x81\x00\x
AC\xCE\xA4\x06\x901\xB5x\x89lE\rw\xC8<\x13\xDDu\xC6h\xBF'b6\x8D\xB0\xA0\xB1Y\e\x
18\x00\xE5\x8C\x1A\xCD\xBB%\xDA\x15P\x1A\xF91\xF9\xF6\xBA\xE0\xF8\xF6LH\x16\x86\
xE9Y\xDE\x00Z\xEC\x82\xB3=\r2fP7\xD1\x8B\xF3k\xF7|MVb\fB\xFB\xBA\x92\xD3\xFF9\x7
F\x9D\x83w\xFE\xAB\xBA\x93G\x8F\xCE\xF0\t!d\x83\xD3F\xAC\xCCv\xCA\x10\xC9\xB8e;\
x80\xB8\xF6\xEBI\xBD\x93\x89zC\xDF\x06-\r\x9E\xD3\x02\x03\x01\x00\x01\xA3\x82\x0
2\xB30\x82\x02\xAF0\v\x06\x03U\x1D\x0F\x04\x04\x03\x02\x03\xF808\x06\b+\x06\x01\
x05\x05\a\x01\x01\x04,0*0(\x06\b+\x06\x01\x05\x05\a0\x01\x86\x1Chttp://ocsp.mult
icert.com/ca0\x81\xE0\x06\x03U\x1D \x04\x81\xD80\x81\xD50M\x06\t+\x06\x01\x04\x0
1\xB0<\n\x020#0>\x06\b+\x06\x01\x05\x05\a\x02\x01\x162http://www.multicert.com/c
ps/multicert-ca-cps.html0\x81\x83\x06\v+\x06\x01\x04\x01\xB0<\n\x02\x88\x060t0r\
x06\b+\x06\x01\x05\x05\a\x02\x020f\x1Ed\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\
x00w\x00w\x00.\x00m\x00u\x00l\x00t\x00i\x00c\x00e\x00r\x00t\x00.\x00c\x00o\x00m\
x00/\x00c\x00p\x00/\x00m\x00u\x00l\x00t\x00i\x00c\x00e\x00r\x00t\x00-\x00c\x00a\
x00-\x001\x000\x003\x000\x00.\x00h\x00t\x00m\x00l0\x11\x06\t`\x86H\x01\x86\xF8B\
x01\x01\x04\x04\x03\x02\x04\xB00 \x06\x03U\x1D\x11\x04\x190\x17\x81\x15info#reci
bosonline.pt0\x82\x01\x01\x06\x03U\x1D\x1F\x04\x81\xF90\x81\xF60\x81\x9A\xA0\x81
\x97\xA0\x81\x94\x86/http://www.multicert.com/ca/multicert-ca-02.crl\x86aldap://
ldap.multicert.com/cn=MULTICERT-CA%2002,o=MULTICERT-CA,c=PT?certificateRevocatio
nList?base0W\xA0U\xA0S\xA4Q0O1\v0\t\x06\x03U\x04\x06\x13\x02pt1\x150\x13\x06\x03
U\x04\n\x13\fMULTICERT-CA1\x180\x16\x06\x03U\x04\x03\x13\x0FMULTICERT-CA 021\x0F
0\r\x06\x03U\x04\x03\x13\x06CRL2950\x1F\x06\x03U\x1D#\x04\x180\x16\x80\x14\x1D\x
C3\xB9\x88\xA5\x18\xBE`\xA7,\xA6c\xCAf*\xFC\f'\xC1\xBD0\x1D\x06\x03U\x1D\x0E\x04
\x16\x04\x14\x06\xD8\x1Fr6a\x9E\xEB\x176\x9C)\x9E-t\xFF\xD080\x190\t\x06\x03U\x1
D\x13\x04\x020\x000\r\x06\t*\x86H\x86\xF7\r\x01\x01\x05\x05\x00\x03\x82\x01\x01\
x00AQ\x1F\xCD\\ua\x98\e\rT2kW\xF7\xB8|CZ\xAC\xB7\xA2\x96(\bv\x83\x13\x89*\xB1#r7
\xE9WW{\x87T\x14\xDE\x81\nA2?\x9E\nv\x8E\x9A\xC4\\\x0Ff\xAE\t<2\xC1\x14S\xC6F?\x
85o\xEFb\xE2x!\x13M\xD0\x9Fu \x80\x00\x04\x0E\x89\xA8\x14\xE60\x96#\xC5\xD0Ac\xC
0<\xFD\xE31S\x90\x8A\xC3\xDF\xCA[\x1Cf\xC3\xDC\xB8\x96D\xA3\x03\x0F\xE7\x94\xD5\
v\xD2U\xD3\x96SZz\xF2g\xC3\xA58\x14{\x93q\xD0_#\xD8\xCAH\x1A\xEB\xC7\xD7\xA7\xD9
|.\x7F\xB5\xABI\xC4\xE4UNH\x00d\x8B\xC7k\x1A\xF5a*\x1D\x93a\xD1r\bNpi\t(\xA9\x11
\xFC \x983\xC5\x06!\x9C\xF1\x86\xB6P{Y\x9EL\x0FB\xF3\xBF#\xC2\xB8\xF0\xA0x\xD0\x
1D\x9B\xF5\xFDGF\xD9rS\xEEO\xE8\xF4rH\x9B=\xC2opr\xC6Xr\x18\x82[\xB3\x06\x10t\xB
9\xC2#\xF8\x92\x8D6\xFE\xFC\x0Fp\x88\x97u,\xD9F1\x82\x01\xC70\x82\x01\xC3\x02\x0
1\x010F0>1\v0\t\x06\x03U\x04\x06\x13\x02pt1\x150\x13\x06\x03U\x04\n\x13\fMULTICE
RT-CA1\x180\x16\x06\x03U\x04\x03\x13\x0FMULTICERT-CA 02\x02\x04Bo\x93\x8C0\t\x06
\x05+\x0E\x03\x02\x1A\x05\x00\xA0\x81\xD80\x18\x06\t*\x86H\x86\xF7\r\x01\t\x031\
v\x06\t*\x86H\x86\xF7\r\x01\a\x010\x1C\x06\t*\x86H\x86\xF7\r\x01\t\x051\x0F\x17\
r130329223127Z0#\x06\t*\x86H\x86\xF7\r\x01\t\x041\x16\x04\x14\x93\xD9l\xBD68\xDB
*M\xADY\xF8\x8F<\x8E\x94m\xACS\xAE0y\x06\t*\x86H\x86\xF7\r\x01\t\x0F1l0j0\v\x06\
t`\x86H\x01e\x03\x04\x01*0\v\x06\t`\x86H\x01e\x03\x04\x01\x160\v\x06\t`\x86H\x01
e\x03\x04\x01\x020\n\x06\b*\x86H\x86\xF7\r\x03\a0\x0E\x06\b*\x86H\x86\xF7\r\x03\
x02\x02\x02\x00\x800\r\x06\b*\x86H\x86\xF7\r\x03\x02\x02\x01#0\a\x06\x05+\x0E\x0
3\x02\a0\r\x06\b*\x86H\x86\xF7\r\x03\x02\x02\x01(0\r\x06\t*\x86H\x86\xF7\r\x01\x
01\x01\x05\x00\x04\x81\x803]\xBC\xA2\xC5\x0F&\r\x94\x96\xD5\xBD\xF2\x96\xB3\x86\
x9D\x01\xA3{5\xEC\xA5\xEC\x8B=\r\xD7%w0o\x9C\x7F\v\x17YX\x80\xAF\x1A\x8F\x1E\xBB
e\xBCp4\xF7\x80\x89b&?\xCE<\xCC\x8D\xFE\xEFK\x86\x0F\xD8Q\xFFU\x04\x11E\t\xED\xC
9=WF\x93\x10w\xC6g\xD4\e`\xE5\xB5{Ax~%\xE9\x92\xF5\x01\x19\xCDS\xE1|%\"\xB2\xC6\
x107\xE9\xF7M\xD7\xA3\x11MJ\xAF\x03\x0F\xFF\x8D:s\x84g\xB6\xD5o\xAF\xB0\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00", /Filter=>/Adobe.PPKMS, /SubFilter=>/adbe.pkcs7.sha1, /
ByteRange=>[0, 12883, 17081, 1098], /Location=>"Portugal", /ContactInfo=>"email#email.com", /Reason=>"Proof of Concept", /M=>"D:20130329223127Z00'00", /P
rop_Build=>{/Filter=>{/Name=>/Adobe.PPKMS, /R=>131101, /Date=>"2013-03-29 22:31:
27 +0000"}, /SigQ=>{/Preview=>false, /R=>131101}, /PubSec=>{/NonEFontNoWarn=>fal
se, /Date=>"2013-03-29 22:31:27 +0000", /R=>131101}, /App=>{/TrustedMode=>false,
/OS=>[/Win], /R=>458752, /Name=>/Exchange-Pro}}}
If i extract the keys (pdf.signature.keys) i get
/Type
/Contents
/Filter
/SubFilter
/ByteRange
/Location
/ContactInfo
/Reason
/M
/Prop_Build
Now, how do I reach the contents of these keys ?
I cannot simply do pdf.signature[/Location] , because ruby says it is a syntax error...
Any ideas?
I took a look at the source for origami-pdf, and it seems that the / prepending every key in that output is generated on-the-fly from Origami::Name.to_s. Also looking at its eql? definition it seems like it just compares it to the underlying string value. So this should work, have you tried it?
signature[Origami::Name.new('Location')]
As generating an Origami::Name object with /Location seems to be so hard, I solved this with a different approach :
location = pdf.signature[pdf.signature.keys[5]]
The Output returns Portugal, and this is the approach I will take, since the array's keys position are supposed to be static.
I would appreciate a more elegant solution though

Remove duplicate items from a hash in Ruby

I am using the Twitter Gem to access the Twitter API and I'd like to create a variable that only stores mentions that are unique, based on the text of the mention.
Right now, I'm storing all mentions like so: #allmentions = Twitter.mentions_timeline
This is an example of a mention returned for #allmentions[0]
=> #<Twitter::Tweet:0x007fbffb59ab88 #attrs={:created_at=>"Mon Dec 10 01:28:11 +0000 2012", :id=>277947788216639488, :id_str=>"277947788216639488", :text=>"#person hi", :source=>"web", :truncated=>false, :in_reply_to_status_id=>nil, :in_reply_to_status_id_str=>nil, :in_reply_to_user_id=>11739102, :in_reply_to_user_id_str=>"11739102", :in_reply_to_screen_name=>"person", :user=>{:id=>1000628702, :id_str=>"1000628702", :name=>"test account", :screen_name=>"testaccountso", :location=>"", :description=>"", :url=>nil, :entities=>{:description=>{:urls=>[]}}, :protected=>false, :followers_count=>0, :friends_count=>0, :listed_count=>0, :created_at=>"Mon Dec 10 01:27:39 +0000 2012", :favourites_count=>0, :utc_offset=>nil, :time_zone=>nil, :geo_enabled=>false, :verified=>false, :statuses_count=>1, :lang=>"en", :contributors_enabled=>false, :is_translator=>false, :profile_background_color=>"C0DEED", :profile_background_image_url=>"http://a0.twimg.com/images/themes/theme1/bg.png", :profile_background_image_url_https=>"https://si0.twimg.com/images/themes/theme1/bg.png", :profile_background_tile=>false, :profile_image_url=>"http://a0.twimg.com/sticky/default_profile_images/default_profile_3_normal.png", :profile_image_url_https=>"https://si0.twimg.com/sticky/default_profile_images/default_profile_3_normal.png", :profile_link_color=>"0084B4", :profile_sidebar_border_color=>"C0DEED", :profile_sidebar_fill_color=>"DDEEF6", :profile_text_color=>"333333", :profile_use_background_image=>true, :default_profile=>true, :default_profile_image=>true, :following=>nil, :follow_request_sent=>false, :notifications=>nil}, :geo=>nil, :coordinates=>nil, :place=>nil, :contributors=>nil, :retweet_count=>0, :entities=>{:hashtags=>[], :urls=>[], :user_mentions=>[{:screen_name=>"person", :name=>"Person", :id=>1173910, :id_str=>"1173910", :indices=>[0, 6]}]}, :favorited=>false, :retweeted=>false}>
I can access the text of the mention like so: #allmentions[0].text
Is there a built-in ruby method (or an easy way) to let me store only the mentions that have a unique value in the text attribute?
Yes, you can call uniq with a block.
For example:
#allmentions.uniq {|m| m.text}
To answer my own question, I did a bit of research, and it seems like this would work:
no_dupes = $allmentions.uniq { |h| h[:text] }

Resources