I have mentioned the same XML in below .
XML :1
<PP XML="2000_4_174.xml">
<P name="Antony" value="IN"/>
<P name="sitting" value="17 AUGUST 2000"/>
<P name="type" value="reported"/>
<P name="startpage" value="174"/>
</PP>
XML :2
<PP XML="2000_4_17411.xml">
<P name="Antony" value="IN"/>
<P name="sitting" value="17 AUGUST 2000"/>
<P name="type" value="reported"/>
<P name="startpage" value="1"/>
</PP>
I have using different condition of in Xpath query for getting #XML value condition(#name ="Antony" and #value="IN" and #name ="startpage" and #value="174") so expect output is (2000_4_174.xml)
I have tried this Query please suggest me how to add the another two conditions.
let $uri := //PP/P[#name="Antony" and #value="IN"]
for $i in $uri
let $j := xdmp:node-uri($i)
let $s :=doc($j)/PP/#XML
return $s
XPath for that would be :
//PP[P[#name="Antony" and #value="IN"]
and
P[#name="startpage" and #value="174"]
]/#XML
The XPath should return XML attribute of <PP> element which contains the following child elements :
<P name="Antony" value="IN"/>
<P name="startpage" value="174"/>
Related
Is it possible to check if a message property exists?
Example: I would like to remove a collapsable div-Element in a loop containing only a message property.
<div th:each="payment : ${paymentList}">
<input type="radio" data-toggle="radio-collapse" data-target="#collapse1" [...] /> [...]
<div id="collapse1" th:utext="#{|payment.${payment.id}.additionalInfo|}" [...]>
Hello, world!
</div>
</div>
If there is no additional info for the payment the element is not necessary.
Lets say we have the IDs DIRECT_DEBIT, PAYPAL and SAFERPAY and the following message properties:
payment.DIRECT_DEBIT=Direct debit
payment.DIRECT_DEBIT.additionalInfo=Direct debit info text...
payment.PAYPAL=PayPal
payment.PAYPAL.additionalInfo=PayPal info text...
payment.SAFERPAY=Saferpay
As you can see there is no additionInfo message property for SAFERPAY.
You should use the #messages object to check if a message exists. For example:
th:if="${#messages.msgOrNull('payment.' + payment.id + '.additionalInfo') != null}"
<div id="collapse1" th:if="${#messages.msgOrNull('payment.' + payment.id + '.additionalInfo') != null}" th:utext="#{|payment.${payment.id}.additionalInfo|}" [...]>
Hello, world!
</div>
You can use th:if to add the element only if it isn't null and isn't equal to a empty string (I don't know how you implemented the object).
<div id="collapse1"
th:if="${payment.${payment.id}.additionalInfo != null && payment.${payment.id}.additionalInfo != ''}"
th:utext="#{|payment.${payment.id}.additionalInfo|}" [...]
>
Hello, world!
</div>
... and you should also change the id property. In your impelementation there could be more than one element with id "collapse1".
If you also don't want to show the input field use a th:block element and place the th:if attribute there:
<div th:each="payment : ${paymentList}">
<th:block
th:if="${ ... && ... }"
>
<input ...>
<div ...>
</div>
</th:block>
</div>
<div id="mDetails">
<span class="textLabel">Bar Number:</span>
<p class="profileText">YYYYYYYYYYYYYYYYYYYY</p>
<span class="textLabel">Address:</span>
<p class="profileText">YYYYYYYYYYYYYYYYYYY<br>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY<br>United States</p>
<span class="textLabel">Phone:</span>
<p class="profileText">123465798</p>
<span class="textLabel">Fax:</span>
<p class="profileText">987654321</p>
<span class="textLabel">Email:</span>
<p class="profileText">regina#rbr3.com</p>
<span class="textLabel">County:</span>
<p class="profileText">YYYYYYYYYYYYYYY</p>
<span class="textLabel">Circuit:</span>
<p class="profileText">YYYYYYYYYY</p>
<span class="textLabel">Admitted:</span>
<p class="profileText">00/00/0000</p>
<span class="textLabel">History:</span>
<p class="profileText">YYYYYYYYYYYYYYYYY</p>
im trying to select the email only if its available cause when i use //*[#class="profileText"]it returns everything with this class , i want only to return when # is present in the value.
With the adjustment to the input XML to change both <br> to <br/> (otherwise it's not valid XML) the following XPath selects all p elements that have the class profileText and contains #:
//p[#class='profileText'][contains(.,'#')]
returns
<p class="profileText">regina#rbr3.com</p>
In case you only want to get the value, you can use string():
string(//p[#class='profileText'][contains(.,'#')])
returns
regina#rbr3.com
Note that string() would only return the value of the first match, while the first XPath returning the p elements returns all matches.
I am new to nokogiri and so far most familiar with CSS selectors, I am trying to parse information from a table, below is a sample of the table and the code I'm using, I'm stuck on the appropriate if statement, as it seems to return the whole contents of the table.
Table:
<div class="holder">
<div class ="row">
<div class="c1">
<!-- Content I Don't need -->
</div>
<div class="c2">
<span class="data">
<!-- Content I Don't Need -->
<span class="data">
</div>
</div>
...
<div class="row">
<div class="c1">
SPECIFIC TEXT
</div>
<div class="c2">
<span class="data">
What I want
</span>
</div>
</div>
</div>
My Script: (if SPECIFIC TEXT is found in the table it returns every "div.c2 span.data" variable - so I've either screwed up my knowledge of do loops or if statements)
data = []
page.agent.get(url)
page.search('div.row').each do |row_data|
if (row_data.search('div.c1:contains("/SPECIFIC TEXT/")').text.strip
temp = row_data.search('div.c2 span.data').text.strip
data << temp
end
end
There's no need to stop and insert ruby logic when you can extract what you need in a single CSS selector.
data = page.search('div.row > div.c1:contains("SPECIFIC TEXT") + div.c2 span.data')
This will include only those that match the selector (e.g. follow the SPECIFIC TEXT).
Here's where your logic may have gone wrong:
This code
if (row_data.search('div.c1:contains("SPECIFIC TEXT")'...
temp = row_data.search('div.c2 span.data')...
first searches the row for the specific text, then if it matches, returns ALL rows matching the second query, which has the same starting point. The key is the + in the CSS selector above which will return elements immediately following (e.g. the next sibling element). I'm making an assumption, of course, that the next element is always what you want.
I'd do
require 'nokogiri'
html = <<_
<div class="holder">
<div class ="row">
<div class="c1">
<!-- Content I Don't need -->
</div>
<div class="c2">
<span class="data">
<!-- Content I Don't Need -->
<span class="data">
</div>
</div>
<div class="row">
<div class="c1">
SPECIFIC TEXT
</div>
<div class="c2">
<span class="data">
What I want
</span>
</div>
</div>
</div>
_
doc = Nokogiri::HTML(html)
css_string = 'div.row > div.c1[text()*="SPECIFIC TEXT"] + div.c2 span.data'
doc.at(css_string).text.strip
# => "What I want"
How those selectors would work here -
[name*="value"] - Selects elements that have the specified attribute with a value containing the a given substring.
Child Selector (“parent > child”) - Selects all direct child elements specified by "child" of elements specified by "parent".
Next Adjacent Selector (“prev + next”) - Selects all next elements matching "next" that are immediately preceded by a sibling "prev".
Class Selector (“.class”) - Selects all elements with the given class.
Descendant Selector (“ancestor descendant”) - Selects all elements that are descendants of a given ancestor.
I have two different type of html code:
my first code is:
<div class="course-general-info hide-for-medium-up">
<!-- TODO: check date format here -->
<div class="headline"><strong>2014-01-27</strong></div>
<div class="subline">Course start</div>
<div class="headline"><strong>2014-04-27</strong></div>
<div class="subline">Course end</div>
<div class="headline">Basis</div>
<div class="subline">Level</div>
</div>
my second code is:
<div class="course-general-info hide-for-medium-up">
<div class="headline">Available Soon</div>
<div class="subline">Course start</div>
<!-- TODO: check date format here -->
<div class="headline">Basis</div>
<div class="subline">Level</div>
</div>
i need to fetch the following value in single Xpath query
2014-01-27 or
Available Soon
my separate xpath queries are:
courseDurationDate = courseDetailData.xpath('//div[#class = "headline"]/strong/text()').extract()
CourseDutaionAvailableSoon = courseDetailData.xpath('//div[#class = "headline"]/text()').extract()
kindly help to write or condition in Xpath query. thanks in advance....
Assuming only one of the 2 divs will appear at the same time, this should do it:
(//div[#class = "headline"]/strong |
//div[#class = "headline" and not(strong)])[1]/text()
a one-liner
div[#class='course-general-info hide-for-medium-up']/div[#class='headline'][1]/descendant::text()
I tried following Xpath Query its worked for me:
courseDurationDate = courseDetailData.xpath('//div[#class = "course-general-info hide-for-medium-up"]/div[#class = "headline"]/strong/text() | \
//div[#class = "course-general-info hide-for-medium-up"]/div[#class = "headline" and not (strong)][1]/text()').extract()
I am aiming to fill an html element of a certain std html class with content
This answer has a pretty complex concat xpath query:
Using DOMDocument to extract from HTML document by class
This class extension will get and fill html nicely:
https://gist.github.com/j0shua/945507
This is the example html i am working with:
<!-- actual content of the page box -->
<div class="masterWidthSet mainContent">
<div class="mainPageContent">
<script type="text/javascript" src="/email_js.js"></script>
<b>Contact us all at the same time...</b><br/>
<div class="messageSent">Thank you for contacting us, we will get back to you as soon as possible.</div>
<table class="contactForm">
<tr><td class="title">Name</td><td class="description"><input type="text" id="sendName" class="text" placeholder="Your name..."></td></tr>
<tr><td class="title">Number (optional)</td><td class="description"><input type="text" id="phoneNo" class="text"placeholder="Your number..."></td></tr>
<tr><td class="title">Email</td><td class="description"><input type="text" id="email" class="text"placeholder="Your email..."></td></tr>
<tr><td class="title">Message</td><td class="description"><textarea id="message" class="text"placeholder="Your message..."></textarea></td></tr>
<tr><td></td><td class="description"><input type="button" class="submit" value="Send us you message..." onclick="sendMessage()"/><span class="description messageStatus" id="messageStatus"></span></td></tr>
</table>
</div>
</div>
I can easily get the innHTML of the element with a single class 'mainPageContent':
require_once WEBROOT_PRIVATE.'scripts/JSLikeHTMLElement.php';
$dom = new \DOMDocument();
$dom->registerNodeClass('DOMElement', 'JSLikeHTMLElement');
$dom->loadHTML( file_get_contents( $file['local_path'] ) );
$xpath = new \DOMXPath($dom);
$elem = $xpath->query('//*[#class="mainPageContent"]')->item(0);
echo $elem->innerHTML;
But as soon as i try to target a element with multiple classes it returns null (i am assuming because the query is looking for a an exact match) eg 'mainContent':
$elem = $xpath->query('//*[#class="mainContent"]')->item(0);
So I tried to use the concat query from the top post but i get 'Call to a member function item()':
$elem = $xpath->query("//*[contains(concat(' ', normalize-space(#class), ' '), ' mainContent ')")->item(0);
So i tried this:
$elem = $xpath->query('//*[class~="mainContent"]')->item(0);
The problem is each time the item(0) results in an error:
Call to a member function item() on a non-object
This guy says the ways i tried should work.. Selecting a css class with xpath
Can anyone point me in the right direction?
Thanks,
J
Scrap all of the above and just use the phpquery library.
Just like jquery for php! bish bash bosh.
http://code.google.com/p/phpquery/