Insert nested XLM nodes if node doesn't exist using Groovy/JavaScript - javascript

Below is the XML I am working with
<Root>
<Employee>
<EmployeeNumber>10105950</EmployeeNumber>
<LastName>Myers Jr</LastName>
<FirstName>Ezell</FirstName>
<MiddleName/>
<JobTitle>Tech Shield Strapper</JobTitle>
<Manager>N</Manager>
<ManagerID>50501273</ManagerID>
<BusinessEmail>10105950#LPnoemail.com</BusinessEmail>
<Location>TX06</Location>
<CostCenter>10200011</CostCenter>
<HomeLocationCode>TX06 10200011</HomeLocationCode>
<cust_HomeLocationCode>
<cust_LocationCode>30</cust_LocationCode>
</cust_HomeLocationCode>
<Username>myers10105950</Username>
<CostCenterName>JASPER OSB Finishing Techshield</CostCenterName>
<WorkContract>A2</WorkContract>
<HireDate>11/14/2002</HireDate>
<PreferredLanguage>1706</PreferredLanguage>
<PreferredName>Ezell</PreferredName>
</Employee>
<Employee>
<EmployeeNumber>10105951</EmployeeNumber>
<LastName>Bean</LastName>
<FirstName>David</FirstName>
<MiddleName>A</MiddleName>
<JobTitle>Sr. FP&A Analyst</JobTitle>
<Manager>N</Manager>
<ManagerID>10129003</ManagerID>
<BusinessEmail>10105951#LPnoemail.com</BusinessEmail>
<Location>TX06</Location>
<CostCenter>11000152</CostCenter>
<HomeLocationCode>TX06 11000152</HomeLocationCode>
<Username>beanda</Username>
<CostCenterName>OSB Finance</CostCenterName>
<WorkContract>A2</WorkContract>
<HireDate>07/05/1994</HireDate>
<PreferredLanguage>1706</PreferredLanguage>
<PreferredName>David</PreferredName>
</Employee>
</Root>
I need help writing a groovy script or javascript to evaluate the XML. If <cust_HomeLocationCode> and its contents exist, then skip, else insert the node with <cust_LocationCode> value equaling '1'.
So far I have been able to add just the <cust_HomeLocationCode> node using below code
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.xml.XmlUtil;
import groovy.util.*;
def Message processData(Message message) {
def body = message.getBody(java.lang.String);
def root = new XmlParser().parseText(body)
root.each { Employee ->
Employee.appendNode("cust_HomeLocationCode", "newfield")
}
message.setBody(XmlUtil.serialize(root));
return message;
}

Related

How to create language selection wrapper from a gist script?

I have a Gist file written in different languages all do the same thing.
So, I would like to create a language select option similar to Google docs documentation.
Is it possible to create such a wrapper class that accepts a Gist script tag and display as above?
As in embed single file, I tried different query command like <script src="https://gist.github.com/gistid.js?language=python">, but none of them work.
This is the processing code that I ended up with.
With some CSS + javascript hide and toggle logic, it would work like google docs documentation.
I'd appreciate it if anyone updates this answer, with css or js.
import requests
from bs4 import BeautifulSoup
def render_gist_by_file(gist_id):
result = requests.get(f'https://gist.github.com/{gist_id}.js', headers=git_credential)
if result.text.startswith("<!DOCTYPE html>"):
return None
result = result.text
result = result.replace("\\/", "/").replace("\\&", "&").replace("\\$", "$").replace("\\<", "<").replace("\\`", "`").replace("\\n", "\n").replace('\\"', '"')
result = html.unescape(result)
result = result.split("document.write('")[-1][:-3]
bs = BeautifulSoup(result, "html.parser")
for tag in bs.find_all(class_="gist"):
file_box = tag.find(class_="file-box")
root = tag.find(class_="file-box")
toggle_div = bs.new_tag('div', attrs={"class": "gist-meta"})
for i, d in enumerate(tag.find_all(class_="file")):
d["class"] = f"file gist-toggle gist-id-{gist_id}"
if i != 0:
file_box.append(d) # combine to first table
for d in tag.find_all(class_="gist-meta"):
siblings = list(d.next_elements)
file_id, file_name = siblings[4].attrs["href"].split("#")[-1], siblings[5]
gist.file_names.append(file_name)
toggle_a = bs.new_tag('a', attrs={"id": file_id, "class": f"gist-toggle gist-id-{gist_id}", "onclick": f"toggle('gist-id-{gist_id}', '{file_id}')", "style": "padding: 0 18px"})
toggle_a.append(file_name)
toggle_div.append(toggle_a)
d.extract() # remove bottom nav
root.insert(0, toggle_div)
for d in islice(tag.find_all(class_="gist-file"), 1, None):
d.extract() # remove except first
gist.html = str(bs)
return gist

trigger javascript function based on python variable value

The following 2 js functions can toggle a button to and from the disabled class. I want the disabled state to depend on the global variable filelength in the python code but cannot think of a simple way to do so. The only way I can think of is to have 2 identical but separate templates, one with the button disabled and one with it enabled.
<script type="text/javascript" language="JavaScript">
function enableButton(button){
document.getElementById(button).removeAttribute('class');
document.getElementById(button).setAttribute("class", "button");
}
function disableButton(button){
document.getElementById(button).setAttribute("class", "disabled");
}
</script>
I intended to use the functions for the following index.html template element.
<button id="Test" class="button disabled" >
Test
</button>
The intended toggling would produce the following alt.html template element which elides the "disabled".
<button id="Test" class="button" >
Test
</button>
It seems silly to require 2 separate templates (index.html and alt.html) to accomplish this toggle, but I cannot think of an alternative that permits me to just alter index.html. Initially I thought jinja2 would provide the functionality needed, but that does not seem correct.
How can I accomplish this without a second template using python and GAE?
For more completeness, below I show the relevant state of my python application next.
import os
import jinja2
import webapp2
import urllib
filelength = 0
class MainPage(BaseHandler):
def get(self):
global filelength
logging.info("text length in Main get: %s " % filelength)
template_values = {'filelength':filelength}
template = JINJA_ENVIRONMENT.get_template('index.html')
self.response.out.write(template.render(template_values))
def post(self):
global filelength
url = self.request.get('URL', None)
text = urllib.urlopen(url).read()
logging.info("text length in Main post: %s " % len(text))
filelength = len(text)
if filelength > 0:
return webapp2.redirect('/alt')
else:
return webapp2.redirect('/')
class AltMainPage(BaseHandler):
def get(self):
global filelength
logging.info("text length in Alt get: %s " % filelength)
template_values = {'filelength':filelength}
template = JINJA_ENVIRONMENT.get_template('alt.html')
self.response.out.write(template.render(template_values))
def post(self):
global filelength
url = self.request.get('URL', None)
text = urllib.urlopen(url).read()
logging.info("text length in Alt post: %s " % len(text))
if filelength > 0:
return webapp2.redirect('/alt')
else:
return webapp2.redirect('/')
return webapp2.redirect('/')
app = webapp2.WSGIApplication([
('/', MainPage),
('/alt', AltMainPage),
],
debug=True)
In the template index.html simply use jinja2 to define the class attribute like this where the value of buttonclass is defined as either button or button disabled in python using the "if ... else" construct.
<button id="Test" class="{{ buttonclass }} " >
Test
</button>

Mandatory slider in oTree/django

I want to use oTree as an alternative for conducting experiments. For this purpose I am looking for a possibility to include mandatory slider questions in forms, i. e. sliders you are required to move before you are able to proceed to the next question. As a start I tried to modify oTrees survey template to achieve a solution for future usage but wasn't able to integrate common approaches like a fieldtracker into the project.
Here are two modified (yet currently after a number of unsuccessful try-outs not really functioning) versions of the models.py and views.py files which give a hint in which direction I want to go. Is there a way to get this to work?
# -*- coding: utf-8 -*-
## models.py
# <standard imports>
from __future__ import division
from django.db import models
from django_countries.fields import CountryField
from model_utils import FieldTracker,
from otree import widgets
from otree.constants import BaseConstants
from otree.db import models
from otree.models import BaseSubsession, BaseGroup, BasePlayer
class Constants(BaseConstants):
name_in_url = 'survey'
players_per_group = None
num_rounds = 1
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
pass
class Player(BasePlayer):
def set_payoff(self):
"""Calculate payoff, which is zero for the survey"""
self.payoff = 0
q_country = CountryField(
verbose_name='What is your country of citizenship?')
q_age = IntegerFielder(verbose_name='What is your age?',
min=13, max=125,
initial=25,
widget=widgets.SliderInput())
q_gender = models.CharField(initial=None,
choices=['Male', 'Female'],
verbose_name='What is your gender?',
widget=widgets.RadioSelect())
tracker = FieldTracker()
crt_bat = models.PositiveIntegerField()
crt_widget = models.PositiveIntegerField()
crt_lake = models.PositiveIntegerField()
Here comes the second file:
# -*- coding: utf-8 -*-
##views.py
from __future__ import division
from . import models
from ._builtin import Page, WaitPage
from otree.common import Currency as c, currency_range
from .models import Constants, integerfieldcustom
class Demographics(Page):
form_model = models.Player
form_fields = ['q_country',
'q_age',
'q_gender']
check_age = q_age.tracker.has_changed()
def q_age_error_message(self, ):
if Demographics.check_age == False:
return 'You must move the slider before you can continue'
class CognitiveReflectionTest(Page):
form_model = models.Player
form_fields = ['crt_bat',
'crt_widget',
'crt_lake']
def before_next_page(self):
self.player.set_payoff()
page_sequence = [
Demographics,
CognitiveReflectionTest
]
Thanks in advance!
There are two ways of doing it: by using JS only, on the client's side, and by using Django at the server side.
The simple JS solution:
in the template add:
{% block scripts %}
<script>
var SliderTouched = false;
var selector = $('[data-slider] input[type="range"]');
selector.change(function() {
SliderTouched = true;
});
$( ".form" ).submit(function( event ) {
if (!SliderTouched){
event.preventDefault();}
});
</script>
{% endblock %}
So until the user triggers change event, the SliderTOuched var is set to False which prevents a form to be submitted. It is a compact way, but you have to deal with showing an error message to the user yourself.
=================
The longer server-side solution is the following:
in models.py define an additional field:
class Player(BasePlayer):
checkslider = models.IntegerField(blank=True)
in views.py in addition to your slider field pass also this extra field that will check that the slider was changed:
class MyPage(Page):
form_model = models.Player
form_fields = ['q_age', 'checkslider']
def checkslider_error_message(self, value):
if not value:
return 'Please make your decision using slider'
in template insert this hidden extra field to html:
<input type="hidden" name="checkslider" value="" id="id_checkslider"/>
and set this field to current slider value as soon as slider is changed:
{% block scripts %}
<script>
var selector = $('[data-slider] input[type="range"]');
selector.change(function() {
$('#id_checkslider').val(selector.val());
});
</script>
{% endblock %}
By default, Django assumes an input is required.
I think that means if you just remove the initial value, it will self-validate.
Also, you called something named "IntegerFielder()." Did you mean models.IntegerField() or is there an import that we're not seeing?
I suggest a slight modification to Philipp's answer.
The code above still triggers the error message if the participant touches the slider, but returns the slider to the default starting position.
To fix this, I used the following script:
{% block scripts %}
<script>
$('input[name=q_age]').on('input', function(){
$('#id_checkslider').val(1);
});
</script>
{% endblock %}
The code changes checkslider from None to 1 when the slider is touched, even if the participant sets the slider to the default starting position.

replace a portion of xml using xpath and xmldom in node.js

I have a huge xml structure which i have attached below,
I am adding update details and adding data to the product tracking module but when i try to change it it will replacing the entire xml with the new xml
Sample xml
<query_by_gtin_response:queryByGtinResponse xmlns:query_by_gtin_response="urn:gs1:tsd:query_by_gtin_response:xsd:1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:gs1:tsd:query_by_gtin_response:xsd:1 QueryByGtinResponse.xsd urn:gs1:tsd:basic_product_information_module:xsd:1 BasicProductInformationModule.xsd urn:gs1:tsd:nutritional_product_information_module:xsd:1 NutritionalProductInformationModule.xsd">
<productData>
<gtin>00000000000509</gtin>
<targetMarket>124</targetMarket>
<informationProviderGLN>1111111133333</informationProviderGLN>
<informationProviderName>Testsub</informationProviderName>
<productDataRecord>
<module>
<bpi:basicProductInformationModule xmlns:bpi="urn:gs1:tsd:basic_product_information_module:xsd:1">
<productName languageCode="en">waka waka</productName>
<brandNameInformation>
<brandName>wowozella</brandName>
</brandNameInformation>
</bpi:basicProductInformationModule>
</module>
<module>
<nfii:nonfoodIngredientInformationModule xmlns:nfii="urn:gs1:tsd:nonfood_ingredient_information_module:xsd:1"/>
</module>
<module>
<product_tracking_information_module>
<variantId>ec9ef090-57c2-11e6-bc2b-51c4bf71f613</variantId>
<status/>
<name>admin#gmail.com</name>
<createdBy>552f5b90b348147e03e49b62</createdBy>
<createdDate>2016-08-01T08:35:38.648Z</createdDate>
<updatedBy>552f5b90b348147e03e49b62</updatedBy>
<updatedDate>2016-08-01T08:35:38.648Z</updatedDate>
<applicationId>webapp</applicationId>
<history>
<createdDate>2016-08-01T08:35:38.648Z</createdDate>
<updatedDate>2016-08-01T08:35:38.648Z</updatedDate>
<status/>
<updatedBy>552f5b90b348147e03e49b62</updatedBy>
<createdBy>552f5b90b348147e03e49b62</createdBy>
<applicationId>webapp</applicationId>
<name>admin#gmail.com</name>
</history>
</product_tracking_information_module>
</module>
</productDataRecord>
</productData>
</query_by_gtin_response:queryByGtinResponse>
the sample xml i want to replace the current full data in product_tracking_information_module with below
<product_tracking_information_module>
<variantId>ec9ef090-57c2-11e6-bc2b-51c4bf71f613</variantId>
<status>deleted</status>
<name>gs1canada</name>
<createdBy>552f5b90b348147e03e49b62</createdBy>
<createdDate>2016-08-01T08:35:38.648Z</createdDate>
<updatedBy>company Id 552f5b62b348147e03e49b61</updatedBy>
<updatedDate>2016-08-01T14:52:23.985Z</updatedDate>
<applicationId>serverlet</applicationId>
<history>
<createdDate>2016-08-01T08:35:38.648Z</createdDate>
<updatedDate>2016-08-01T08:35:38.648Z</updatedDate>
<status/>
<updatedBy>552f5b90b348147e03e49b62</updatedBy>
<createdBy>552f5b90b348147e03e49b62</createdBy>
<applicationId>webapp</applicationId>
<name>admin#gmail.com</name>
</history>
<history status="deleted">
<applicationId/>
<updatedBy>company Id 552f5b62b348147e03e49b61</updatedBy>
<updatedDate>2016-08-01T14:52:23.985Z</updatedDate>
<name>gs1canada</name>
</history>
</product_tracking_information_module>
and the code to do that, where doc is the xmldom parsed Document
var ptimdom = new dom().parseFromString(ptimxml.toString());
var nodesPTIM = xpath.select("//productData//productDataRecord//module//product_tracking_information_module", doc);
doc.replaceChild(ptimdom,nodesPTIM[0]);
but the result is that the doc after this is the second xml only and the full data is lost.
What am i doing wrong?
Try nodesPTIM[0].parentNode.replaceChild(ptimdom, nodesPTIM[0]), that is call the replaceChild method on the parentNode of the element you want to replace.

Scrape Javascript-generated page using Scrapy

The following page gives access to product details by executing a Javascript request:
http://www.ooshop.com/ContentNavigation.aspx?TO_NOEUD_IDMO=N000000013143&FROM_NOEUD_IDMO=N000000013131&TO_NOEUD_IDFO=81080&NOEUD_NIVEAU=2&UNIVERS_INDEX=3
Each product has the following element:
<a id="ctl00_cphC_pn3T1_ctl01_rp_ctl00_ctl00_lbVisu" class="prodimg" href="javascript:__doPostBack('ctl00$cphC$pn3T1$ctl01$rp$ctl00$ctl00$lbVisu','')"><img id="ctl00_cphC_pn3T1_ctl01_rp_ctl00_ctl00_iVisu" title="Visualiser la fiche détail" class="image" onerror="this.src='/Media/images/null.gif';" src="Media/ProdImages/Produit/Vignettes/3270190199359.gif" alt="Dés de jambon" style="height:70px;width:70px;border-width:0px;margin-top:15px"></a>
I try to use FormRequest from Scrapy librairies to crawl these pages but it does not seem to work:
<python>
import scrapy
from scrapy.http import FormRequest
from JStest.items import JstestItem
class ooshoptest2(scrapy.Spider):
name = "ooshoptest2"
allowed_domains = ["ooshop.com"]
start_urls = ["http://www.ooshop.com/courses-en-ligne/ContentNavigation.aspx?TO_NOEUD_IDMO=N000000013143&FROM_NOEUD_IDMO=N000000013131&TO_NOEUD_IDFO=81080&NOEUD_NIVEAU=2&UNIVERS_INDEX=3"]
def parse(self, response):
URL=response.url
path='//div[#class="blockInside"]//ul/li/a'
for balise in response.xpath(path):
jsrequest = response.urljoin(balise.xpath('#href').extract()[0]
js="'"+jsrequest[25:-5]+"'"
data = {'__EVENTTARGET': js,'__EVENTARGUMENT':''}
yield FormRequest(url=URL,
method='POST',
callback=self.parse_level1,
formdata=data,
dont_filter=True)
def parse_level1(self, response):
path='//div[#class="popContent"]'
test=response.xpath(path)[0].extract()
print test
item=JstestItem()
yield item
Does anyone knows how to make this work?
Many thanks!

Categories

Resources