jaxb moxy xpath preceding-sibling - xpath

I have the following xml and for the life of me cannot get preceding-sibling or following-sibling to work. I've tried these with no luck.
I would like to get the sibling just before the Category element that has name attribute that equals "sporting". So it would be the Group element i want. None of these work:
Transaction/Animals/Dog/Boxers/Boxer/Category[#name='sporting']/preceding-sibling::
Transaction/Animals/Dog/Boxers/Boxer/Category[#name='sporting']/preceding-sibling::[1]
Transaction/Animals/Dog/Boxers/Boxer/Category[#name='sporting']/preceding-sibling::Group
Cant even get previous boxer....none of these work.
Transaction/Animals/Dog/Boxers/Boxer[#name='Butch']/preceding-sibling::
Transaction/Animals/Dog/Boxers/Boxer[#name='Butch']/preceding-sibling::Boxer
Transaction/Animals/Dog/Boxers/Boxer[#name='Butch']/preceding-sibling::[1]
Transaction/Animals/Dog/Boxers/Boxer[#name='Butch']/preceding-sibling::[*]
--thanks
<Transaction>
<Animals>
<Dog>
<Boxers>
<Boxer id="46436">
<Transaction source="kennel"/>
<Category name="local"/>
</Boxer>
<Boxer name="Spike">
<Group id="456"/>
<Category name="sporting"/>
</Boxer>
</Boxers>
</Dog>
<Dog>
<Location Storee="pet store"/>
<Boxers>
<Boxer id="345739">
<Submission Source="store"/>
<Category name="local"/>
</Boxer>
<Boxer name="Butch">
<Group id="123"/>
<Category name="sporting"/>
</Boxer>
</Boxers>
<Additional>
<EffectiveDate>2015-03-01</EffectiveDate>
<ExpirationDate>2016-03-01</ExpirationDate>
</Additional>
</Dog>
</Animals>
</Transaction>

Well, figured out that moxy doesn't do axis. Which is ridiculous.
EclipseLink MOXy #XmlPath support for axes/parent

Related

Using XPath to select events that do not match other criteria in Windows event logs

I am trying to develop a Xpath 1.0 compatible filter abiding by the limitations as noted in the answer to Using XPath starts-with or contains functions to search Windows event logs that will match events with event id of 4771 as long as they do not have a certain computer name. Here is sample xml for a 4771 event I do not want to match/display in event viewer.
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{94849225-5448-4994-A5BA-1E3B0928C30D}" />
<EventID>4771</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>14339</Task>
<Opcode>0</Opcode>
<Keywords>0x8010000000000000</Keywords>
<TimeCreated SystemTime="2017-03-22T20:13:28.105262600Z" />
<EventRecordID>4368371459</EventRecordID>
<Correlation />
<Execution ProcessID="564" ThreadID="1340" />
<Channel>Security</Channel>
<Computer>sample.computer.net</Computer>
<Security />
</System>
<EventData>
<Data Name="TargetUserName">abc$</Data>
<Data Name="TargetSid">S-1-5-21-376469911-3458163162-136990061-477177</Data>
<Data Name="ServiceName">krbtgt/computer.net</Data>
<Data Name="TicketOptions">0x40810010</Data>
<Data Name="Status">0x18</Data>
<Data Name="PreAuthType">2</Data>
<Data Name="IpAddress">::ffff:10.0.0.1</Data>
<Data Name="IpPort">56815</Data>
<Data Name="CertIssuerName" />
<Data Name="CertSerialNumber" />
<Data Name="CertThumbprint" />
</EventData>
</Event>
And here is the unsuccessful filter I have tried. The event is displayed so it is not being properly filtered out, i.e. the targetusername exclusion is not being handled properly.
<QueryList>
<Query Id="0" Path="ForwardedEvents">
<Select Path="ForwardedEvents">*[System[(EventID=4771)]] and *[EventData[Data[#Name='TargetUserName'] and (Data!='abc$')]]</Select>
</Query>
</QueryList>
It appears the (Data!='abc$') portion is being applied to all the Data elements and as long as there is one Data element that does not match the specified value the entire event matches. The intent is that if there is a combination of Data element with a TargetUserName attribute and the value of that element is abc$ then the entire event should not match.
you've correctly understood
*[EventData[Data[#Name='TargetUserName'] and (Data!='abc$')]]
as matching any data element that isn't 'abc$'. What you want is to only consider TargetUserName elements.
*[EventData[Data[#Name='TargetUserName']!='abc$']]
In normal XPath 1.0 environment we can do what you described this way :
*[System/EventID=4771 and EventData/Data[#Name='TargetUserName' and .!='abc$']]
Apparently Windows Event Log's XPath doesn't support any of the following, which left us in a dead-end : ., self::, text(), node(). The closest we can get using XPath might be by assuming that 'TargetUserName', if exists in a given EventData, always appear as the first Data child so we can do as follows :
*[System/EventID=4771 and EventData[Data[1]/#Name='TargetUserName' and Data[1]!='abc$']]

XPath results based on two nodes

I have XML that has a lot of duplicated values. I'd like to select all the rows with a specific section ("sec") and section tag ("sec_tag"), but I can't seem to get the XPath correct.
Here's a small snippet of the XML:
<root>
<record>
<sec>5</sec>
<sec_tag>919</sec_tag>
<nested_tag>
<info>Info</info>
<types>
<type>1</type>
<type>2</type>
<type>3</type>
</types>
</nested_tag>
<flags>00000000</flags>
</record>
<record>
<sec>5</sec>
<sec_tag>930</sec_tag>
<nested_tag>
<info>Info</info>
<types>
<type>1</type>
<type>2</type>
<type>3</type>
</types>
</nested_tag>
<flags>00000000</flags>
</record>
<record>
<sec>7</sec>
<sec_tag>919</sec_tag>
<nested_tag>
<info>Info</info>
<types>
<type>1</type>
<type>2</type>
<type>3</type>
</types>
</nested_tag>
<flags>00000000</flags>
</record>
</root>
I want the node that has <sec>5</sec> and <sec_tag>919</sec_tag>.
I tried something like this:
//sec[text(), "5"] and //sec_tag[text(), "919"]
Obviously that's not the correct syntax there, I just need to find the correct XPath expression.
You can use the following XPath expression to return record elements having child sec equals 5 and sec_tag equals 919 :
//record[sec = 5 and sec_tag = 919]

Replacing xml tags in BASH

I have a large collection of xml documents with a wide array of different tags in them. I need to change all tags of the form <foo> and turn them into tags of the form <field name="foo"> in a way that will also ignore the attributes of a given tag. That is, a tag of the form <foo id="bar"> should also be changed to the tag <field name="foo">.
In order for this transformation to work, I also need to distinguish between <foo> and </foo>, as </foo> must go to </field>.
I have played around with sed in a bash script, but to no avail.
Although sed is not ideal for this task (see comments; further reading: regular, context-free grammar and xml), it can be pressed into service. Try this one-liner:
sed -e 's/<\([^>\/\ ]*\)[^>]*>/<field name=\"\1\">/g' -e 's/<field name=\"\">/<\/field>/g' file
First it will replace all end tags with </field>, then replace every open tag first words with <field name="firstStoredWord">
This solution prints everything on the standard output. If you want to replace it in file directly when processing, try
sed -i -e 's/<\([^>\/\ ]*\)[^>]*>/<field name=\"\1\">/g' -e 's/<field name=\"\">/<\/field>/g' file
That makes from
<html>
<person>
but <person name="bob"> and <person name="tom"> would both become
</person>
this
<field name="html">
<field name="person">
but <field name="person"> and <field name="person"> would both become
</field>
Sed is the wrong tool for the job - a simple XSL Transform can do this much more reliably:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="foo">
<field name="foo">
<xsl:apply-templates/>
</field>
</xsl:template>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note that unlike sed, it can handle short empty elements, newlines within tags (e.g. as produced by some tools), and just about anything that's well-formed XML. Here's my test file:
<?xml version="1.0"?>
<doc>
<section>
<foo>Plain foo, simple content</foo>
</section>
<foo attr="0">Foo with attr, with content
<bar/>
<foo attr="shorttag"/>
</foo>
<foo
attr="1"
>multiline</foo
>
<![CDATA[We mustn't transform <foo> in here!]]>
</doc>
which is transformed by the above (using xsltproc 16970175.xslt 16970175.xml) to:
<?xml version="1.0"?>
<doc>
<section>
<field name="foo">Plain foo, simple content</field>
</section>
<field name="foo">Foo with attr, with content
<bar/>
<field name="foo"/>
</field>
<field name="foo">multiline</field>
We mustn't transform <foo> in here!
</doc>

traversing ruby map issues

I'm pulling the following XML from mediawiki API
<?xml version="1.0"?>
<api>
<query>
<pages>
<page pageid="309311" ns="0" title="Chenonetta jubata">
<images>
<im ns="6" title="File:Australian Wood Duck.jpg" />
<im ns="6" title="File:Australian Wood Duck Female.JPG" />
<im ns="6" title="File:Australian Wood Duck Male.JPG" />
...
</images>
</page>
</pages>
</query>
</api>
and reading it into a Ruby map using xmlSimple. The data which I'm really trying to get is the image names from the images section but when I attempt to go past the query level with
x= result['query']['pages']
puts x
I'm getting the following error:
in `[]': can't convert String into Integer (TypeError)
what am I doing wrong?
Thanks,
m
I used Nokogiri in the end which allows xpath notation to traverse the xml tree.
e.g.
licenseinfo = results3.xpath("//api/query/pages/page/categories/cl/#title")

How to reference an XML attribute using XPath?

My XML:
<root>
<cars>
<makes>
<honda year="1995">
<model />
<!-- ... -->
</honda>
<honda year="2000">
<!-- ... -->
</honda>
</makes>
</cars>
</root>
I need a XPath that will get me all models for <honda> with year 1995.
so:
/root/cars/makes/honda
But how to reference an attribute?
"I need a XPath that will get me all models for <honda> with year 1995."
That would be:
/root/cars/makes/honda[#year = '1995']/model
Try /root/cars/makes/honda/#year
UPDATE: reading your question again:
/root/cars/makes/honda[#year = '1995']
Bottom line is: use # character to reference xml attributes.

Resources