Getting a value of a node in an XML file - powershell

I'm trying to write a script that will get the value of a node in multiple XML files.
Here is the XML structure :
<Report>
<ReportSections>
<ReportSection>
<Body>
<ReportItems>
<Textbox Name="lbReportName">
<Paragraphs>
<Paragraph>
<TextRuns>
<TextRun>
<Value>Activity Report</Value>
</TextRun>
</TextRuns>
</Paragraph>
</Paragraphs>
</Textbox>
</ReportItems>
</Body>
</ReportSection>
</ReportSections>
</Report>
I use this script to search through the XML :
Select-XML -Path "N:\TEMP\XML\0.xml" –Xpath "//*[#Name='lbReportName']"
(Because the structure is not the same above the name "lbReportName").
Now, how can I get the value "Activity Report" ?
(After the name "lbReportName", the structure is the same for all XML files)

After the name "lbReportName", the structure is the same for all XML files
That makes it easier - since you already have a wildcard selector with an appropriate clause for the "common ancestor", it's as easy as just describing the rest of the path down to the <Value> nodes:
$ValueNodes = Select-Xml ... "//*[#Name='lbReportName']/Paragraphs/Paragraph/TextRuns/TextRun/Value"
# Let PowerShell's property enumeration behavior tackle the rest
$Values = $ValueNodes.Node.InnerText

Related

Parse RSS and if date matches current date then proceed to download

Idea is to check RSS feed for <updated> </updated> if the RSS Updated header is updated matching the date that it is currently being run to then proceed to download.
Sample RSS Feed:
<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text"> Updates</title>
<subtitle type="html"><![CDATA[Latest updates]]></subtitle>
<link href="http://website/website.rss"></link>
<id>http://website</id>
<link rel="alternate" type="text/html" href="http://website/website.rss" ></link>
<link rel="self" type="application/atom+xml" href="https://website/site/download" ></link>
<logo>http://website/website</logo>
<updated>2020-03-28 T17:32:48+00:00</updated>
<entry>
<author>
<name>ueam</name>
</author>
<title type="text"><![CDATA[2.0.4516]]></title>
<link rel="alternate" type="text/html" href="https://website/site/download"></link>
<id>https://website/site/download</id>
<summary type="html"><![CDATA[<ul>
<li>Patched for March 23rd update</li>
<li>Fixed known bug JIRA</li>
</ul>]]></summary>
<content type="html"><![CDATA[]]></content>
<updated>2020-03-28 17:32:48</updated>
</entry>
<entry>
<author>
<name>Team</name>
</author>
<title type="text"><![CDATA[2.0.4516]]></title>
<link rel="alternate" type="text/html" href="https://website/site/download"></link>
<id>https://website/site/download</id>
<summary type="html"><![CDATA[<ul>
<li>
Patch for March 23rd update
</li>
</ul>]]></summary>
<content type="html"><![CDATA[]]></content>
<updated>2020-03-28 17:32:48</updated>
</entry>
<entry>
<author>
<name>Team</name>
</author>
<title type="text"><![CDATA[2.0.4514]]></title>
<link rel="alternate" type="text/html" href="https://website/site/download></link>
<id>https://website/site/download</id>
<summary type="html"><![CDATA[<ul>
<li>Fixed Bug</li>
Here
<updated>2020-03-28 17:32:48</updated>
is shown which if I was running today then would proceed to download since it matches the current day
The download would then called via
Invoke-WebRequest -uri https://website/site/download
I am just not sure how to parse the RSS to look at the "updated" and compare against current date and if date matches then proceed to download.
Update:
I tried the below
#Grab RSS
$rssString = Invoke-WebRequest "http://website/website.rss"
# convert rss to xml
$xml = [xml] $rssString
# select the <updated> node
$updateString = $xml.SelectSingleNode("/feed/updated").innerText
# convert string to date
$date = Get-Date $updateString
# compare to todays date
if($date.Date -eq (Get-Date).Date){
# proceed to download
}
You get this error:
Get-Date : Cannot bind parameter 'Date' to the target. Exception setting "Date": "Cannot convert null to type "System.DateTime"."
When you run
$updatestring
nothing is returned and is blank, seems that the updated node is not being read
RSS is xml, so treat it as such :)
The <updated> node immediately under the root <feed> seems to reflect the latest update, so grab that:
# convert rss to xml
$xml = [xml]$rssString;
# select the <updated> node
$updateString = $xml.SelectSingleNode("/feed/updated").innerText
# convert string to date
$date = Get-Date $updateString
# compare to todays date
if($date.Date -eq (Get-Date).Date){
# proceed to download
}

InteractiveBarChart: How to Bind Model

I can't find any example about binding a JSON model to an InteractiveBarChart in an XML view.
My view is the following:
<core:View
xmlns:core="sap.ui.core"
xmlns:m="sap.m"
xmlns="sap.f"
xmlns:f="sap.f"
xmlns:smartFilterBar="sap.ui.comp.smartfilterbar"
xmlns:mc="sap.suite.ui.microchart"
xmlns:layout="sap.ui.layout"
xmlns:customData="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"
controllerName="webui.controller.Logger.HomeLogger"
height="100%"
>
<DynamicPage id="dynamicPage"
navButtonPress="onNavBack"
showNavButton="true"
>
<title>
<f:DynamicPageTitle>
<f:heading>
<m:Title text="Methode Logger" />
</f:heading>
<f:expandedContent>
<m:Text text="System analysis" />
</f:expandedContent>
<f:actions>
<m:ToolbarSpacer />
<m:Button
icon="sap-icon://action-settings"
binding="{securitySystem>/}"
press="onSettingsPress"
visible="{securitySystem>enabledApplications/enableSettingsAdmin}"
/>
</f:actions>
</f:DynamicPageTitle>
</title>
<header>
<DynamicPageHeader>
<content>
<layout:Grid defaultSpan="XL6 L6 M6 S12">
<m:FlexBox
width="20rem"
height="10rem"
alignItems="Center"
class="sapUiSmallMargin"
>
<m:items>
<mc:InteractiveBarChart
labelWidth="25%"
selectionChanged="chartSelectionChanged"
press="press"
bindBars="{/}"
>
<mc:bars>
<mc:InteractiveBarChartBar
label="{key}"
value="{value}"
/>
</mc:bars>
</mc:InteractiveBarChart>
</m:items>
</m:FlexBox>
</layout:Grid>
</content>
</DynamicPageHeader>
</header>
</DynamicPage>
</core:View>
I've to bind the InteractiveBarChart to my model, an array set in the controller. By SAP reference, I've to use bindBars method, but I can't make it work.
Any control in UI5 has the same concepts of data binding: property and aggregation bindings.
If control is aimed to show multiple things (i.e. table or list), it will have the so called aggregation.
In InteractiveBarChart control there is an aggregation "bars".
Any control can be bound against model via the unified binding syntax.
For programmatic binding is the following template: "bind{NAME OF AGGREGATION}". So in this case it will be "bindBars" method, which takes the same list of arguments as any aggregation binding;
For declaration binding in XML, you have to do 2 things:
tell the control about data source. In your case you should set the control's property with the name of aggregation "bars" to the binding string "{/}", in case you store the raw array in the root property of a default model (i.e. model without name)
define a template, which will be used as a basis of creation of a list of bars (you've already done it correctly)

Can't fetch mail body using gmail contextual gadget

Here is my manifest.xml file
<?xml version="1.0" encoding="UTF-8" ?>
<ApplicationManifest xmlns="http://schemas.google.com/ApplicationManifest/2009">
 
  <Name>My test gadget</Name>
  <Description>Test Gmail contextual gadgets for mail body</Description>
 
 
<Extension id="MailBodyReaderGadget" type="contextExtractor">
  <Name>Mail Body Reader Gadget</Name>
  <Url>google.com:EmailBodyExtractor</Url>
<Param name="body" value=".*" /> 
  <Triggers ref="mailBodyTextWidget" /> 
  <Scope ref="emailBody" />
  <Container name="mail" />
</Extension>
 
<!-- our GADGET -->
<Extension id="mailBodyTextWidget" type="gadget">
  <Name>Get mail body</Name>
  <Url>http://test.com/spec.xml</Url>
  <Container name="mail" />
</Extension>
 
<!-- gadget Scope -->
<Scope id="emailBody">
  <Url>tag:google.com,2010:auth/contextual/extractor/BODY</Url>
  <Reason>This app will show the mail body text when you click the button "Show Mail Body"</Reason>
</Scope>
</ApplicationManifest>
and spec.xml file
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs
height="200"
author=""
author_email=""
author_location="US">
        <Require feature="dynamic-height"/>
        <Require feature="google.contentmatch">
            <Param name="extractors">
                google.com:EmailBodyExtractor
            </Param>
        </Require>
    </ModulePrefs>
    <Content type="html" view="card">
<![CDATA[      
<script type="text/javascript">
document.write([
"\<script src='",
("https:" == document.location.protocol) ? "https://" : "http://",
"ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js' type='text/javascript'>\<\/script>"
].join(''));
</script>
<button id="btn">Show Mail Body</button>
<div id="widget" style="heigth:300px;width:500px;">
</div>
    <script>
        matches = google.contentmatch.getContentMatches();
        for (var match in matches) {
          for (var key in matches[match]) {                     
            $("#widget").html(matches[match][key]);           
          }
        }       
    </script>    
    ]]>
  </Content>
</Module>
This is my code, i have been tried to fetch mail subject and from and to email addresses it has been worked. But the main issue is i can't fetch mail body. Is there any solution to fix this?
The answer is to delete the node <Param name="body" value=".*" />
This one had me stuck, as I thought that the <param> node was required to define the name of the output parameter to use in our gadget.
But in fact the MailBodyReaderGadget outputs the parameter of "body" automatically.
So the <Param> node is only used if you wish to filter the output.
As you always want to output the body, you can delete this node entirely.
The reason it is not working at the moment is because the .* filter doesn't match return characters (which will be in the body)

How to extend Zend_Form prefix path while configuring form through XML (Zend_Config) to load custom form elements?

I'm loading my Zend_Form from an XML file :
<form>
<elements>
<role>
<type>MyProject_Form_Element_Select_Roles</type>
<options>
<label>Role:</label>
<value></value>
</options>
</role>
<valid>
<type>submit</type>
<options>
<label>Valid</label>
</options>
</valid>
</elements>
</form>
Of course the XML below doesn't work since Zend doesn't know how to load my custom field (which is just an extension of Zend_Form_Element_Select), but the line below doesn't work, if anyone can help :
<form>
<elementPrefixPath>
<prefix>MyProject_Form_Element_Select</prefix>
<path>MyProject/Form/Element/Select</path>
<type>element</type>
</elementPrefixPath>
...
I found these config features really cool but finding info or tutorial on them is really tough (I know there's some mapping rule between the Zend_Form objects structure and the expected config file, but I do never found a complete description of it if someone has a link)
Here's the correct form XML description :
<form>
<prefixPath>
<element>
<prefix>MyProject_Form_Element_Select</prefix>
<path>MyProject/Form/Element/Select</path>
</element>
</prefixPath>
<prefixPath>
<element>
<prefix>MyLib_Form_Element_Select</prefix>
<path>MyLib/Form/Element/Select</path>
</element>
</prefixPath>
<elements>
<role>
<type>Roles</type>
<options>
<label>Role:</label>
<value></value>
</options>
</role>
<valid>
<type>submit</type>
<options>
<mycustomoption></mycustomoption>
<label>Valid</label>
</options>
</valid>
</elements>
</form>
The custom options will be send inside the $options argument of the constructor of your Element
class MyProject_Form_Element_Select_Roles extends Zend_Form_Element_Select
{
public function __construct($spec, $options = null) {
//don't forget to call parent !
//$options is a Zend_Config that should have as a member mycustomptions
}
}

dynamically creating ids of macro components using arguments

I am trying to create two grids which perform exactly the same function without having to duplicate the code of the code for the grid twice. So, I decided to use a macro component. But, I am not sure how to create the ids of the components in the macro component dynamically. The code does the following:
The first grid(west region) has two rows with two textboxes. If I add "hello" to the first textbox in this grid then the value of the second textbox is also set to "hello".
The second grid(center region) has two rows with two textboxes. If I add "world" to the first textbox in this grid then the value of the second textbox is also set to "world"
The values of both textboxes in the first grid are now same i.e. "hello"
The values of both textboxes in the second grid are now same i.e. "world"
I created a zul file in which I use a macro component like so:
<?component name="mygrid1" macro-uri="grid1.zul" inline="true"?>
<zk>
<vbox hflex="1">
<borderlayout height="500px" width="500px">
<west size="50%">
<mygrid1 id="grid1" index="1" />
</west>
<center>
<mygrid1 id="grid2" index="2" />
</center>
</borderlayout>
</vbox>
</zk>
<zscript>
fillInDuplicateBox(String value, Textbox duplicateBox) {
if (!"".contentEquals(duplicateBox.value))
return;
duplicateBox.value = value;
}
</zscript>
</window>
Macro component is shown below:
<zk>
<vbox hflex="1">
<grid width="300px">
<rows>
<row> Box 1: <textbox id="${concat("newBox", arg.index)}" onChange="fillInDuplicateBox(${concat("newBox, arg.index)}.value, ${concat("duplicateBox", arg.index)})" hflex="1" /></row>
<row> Box 2: <textbox id="${concat("duplicateBox", arg.index)}" hflex="1" /></row>
</rows>
</grid>
</vbox>
</zk>
I also tried the following code to create the macro component
<zk>
<vbox hflex="1">
<grid width="300px">
<rows>
<row> Box 1: <textbox id="newBox${arg.index}" onChange="fillInDuplicateBox(newBox${arg.index}.value, duplicateBox${arg.index})" hflex="1" /></row>
<row> Box 2: <textbox id="duplicateBox${arg.index}" hflex="1" /></row>
</rows>
</grid>
</vbox>
</zk>
None of this works. I am not sure how to dynamically create the ids of the components in the macro component. The textbox ids of the first grid must be "newBox1", "duplicateBox1" and the textbox ids of the second grid must be "newBox2", "duplicateBox2"
Please point out if there is a better way of achieving this task.
Thanks,
Sony
I am not sure if it is possible to dynamically create ids like that, but I am pretty certain it would be better to avoid it. There are better ways to do this by avoiding the id problem altogether and to use data binding or event handling instead. Your example indicates the main purpose for each grid is to copy the value of one Textbox to a different Textbox - I imagine there is something bigger you are trying to achieve so let us know if this answer leads you to what you need or not.
I have simplified and expanded your sample to give two examples, the first uses the onChanging to immediately copy as you type. The second pair of boxes uses databinding.
<?component name="mygrid1" macro-uri="/grid1.zul" ?>
<zk>
<window>
<vbox hflex="1">
<mygrid1 id="grid1" myGridTitle="First" />
<mygrid1 id="grid2" myGridTitle="Another" />
</vbox>
</window>
</zk>
Here is the macro component in grid1.zul:
<zk>
<zscript><![CDATA[
String myBoundString = "initial value";
]]></zscript>
<vbox hflex="1">
<grid>
<rows>
<row>
<hbox><label value="${arg.myGridTitle}" /> Source</hbox>
<textbox id="originalText" hflex="1" onChanging="duplicateText.value = event.value" />
</row>
<row>
<hbox><label value="${arg.myGridTitle}" /> Source copies here:</hbox>
<textbox id="duplicateText" hflex="1" />
</row>
<row>
Bound to myBoundString:
<textbox id="boundText1" value="#{myBoundString}" hflex="1" />
</row>
<row>
Bound to boundText1:
<textbox id="boundText2" value="#{boundText1.value, load-when=boundText1.onChange}" hflex="1" />
</row>
</rows>
</grid>
</vbox>
</zk>
In the databinding example, you have to change "intial value" and then tab away before the binder updates boundText2. Also notice that the TextBoxes do have ids (boundText1 and boundText2) but that has no impact on achieving the expected functionality in multiple instances of the macro component.