I need to convert the input XML to output as shown below
Input
<root>
<MOD_FACTOR>10</MOD_FACTOR>
<X_MOD_FACTOR>20</X_MOD_FACTOR>
</root>
Ouput
------
<root>
<Data>
<Name> MOD_FACTOR</Name>
<Value>10</Value>
</Data>
<Data>
<Name>X_MOD_FACTOR</Name>
<Value>20</Value>
</Data>
</root>
What is the best way to do this?
You should look at the "Looping functoid" examples. They show a very similar problem.
Related
I need to delete several occurrences of a symbol (single quote) within comments in an XML file in R, and then save it back to XML. I have to do this in 1000s of XML file.
In each XML file the single quote appears more than 50 times and present in different child hierrachial structure (some in child and some in sub-child). But always present within the comments.
I Tried using XML package in R. I first tried to enable this one XML file, but didn't know how to proceed further.
library(XML);library(xml2);library(methods);library(tidyverse)
#Read one XML file
filepath <- "C:/Users/PeriaPr/Desktop/repex1.xml"
onefile <- xmlTreeParse(gsub("'","",readLines(filepath)),asText = TRUE)
xmlroot <- xmlRoot(onefile)
var <- xmlSApply(xmlroot, function(x) xmlSApply(x, xmlValue))
Here is a reproducible example of my XML file. The single quotes (around Orange, Apple and Banana) need to be removed in this multiple tree hierarchical structure. The quotes occur almost 50 times within one XML file, and I need to process (delete single quotes) 1000s of XML files
<?xml version = "1.0" encoding = "windows-1252"?><document id="myrepex.xml">
<action_step step_no="1.3.1.1">
<step>1</step>
<title><![CDATA[Part1 - 'Apple']]></title>
<start><![CDATA[2019/08/09 7:57:17]]></start>
<duration><![CDATA[0 Hr. 12 Min. 22 Sec.]]></duration>
<status><![CDATA[Passed]]></status>
</action_step>
<action_step step_no="1.4.1.1">
<step>2</step>
<title><![CDATA[Part2 - 'Orange']]></title>
<start><![CDATA[2019/08/09 8:09:39]]></start>
<duration><![CDATA[0 Hr. 32 Min. 55 Sec.]]></duration>
<status><![CDATA[Passed]]></status>
</action_step>
<action_step step_no="1.5.1.1">
<step>68</step>
<title><![CDATA[Part3 - 'Banana']]></title>
<start><![CDATA[2019/08/09 8:42:35]]></start>
<duration><![CDATA[0 Hr. 36 Min. 28 Sec.]]></duration>
<status><![CDATA[Passed]]></status>
</action_step>
<action_step2 secondchild="secondchild">
<action_step2subchild subchild="subchild">
<title><![CDATA[Part3 - 'Banana']]></title>
</action_step2subchild>
</action_step2>
To delete all single quotes in the content of title elements, you can use the following XSLT 3.0 stylesheet:
<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="title/text()">{translate(.,"'","")}</xsl:template>
</xsl:transform>
If you want to retain the CDATA tagging (which is considered by XSLT to be pure noise), add an xsl:output declaration with cdata-section-elements attribute.
To apply this transformation to many source XML files, you could either (a) use Saxon's ability to process all files in a directory from the command line, (b) put the control logic within the XSLT stylesheet (using the collection() function), or (c) use some external control logic, e.g. XProc, Ant, or a shell script.
Consider this XSLT 1.0 script and then iterate with R's xslt package (extension of xml2):
XSLT (save as .xsl file to be read in R)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"
cdata-section-elements="title start duration status"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="single_quote">'</xsl:variable>
<xsl:template match="title">
<xsl:copy>
<xsl:value-of select="translate(., $single_quote, '')"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Online Demo
R
library(xml2)
library(xslt)
# RETRIEVE ALL XML FILES
setwd("C:/path/to/xml/files")
xmls <- list.files(pattern="xml")
# LOAD XSLT
style <- read_xml('C:/path/to/Script.xsl', package = "xslt")
# USER-DEFINED METHOD
proc_xml <- function(xml_file) {
# LOAD XML AND XSLT
doc <- read_xml(xml_file)
# TRANSFORM XML
new_xml <- xslt::xml_xslt(doc, style)
# SAVE NEW XML (REMOVE paste0 TO OVERWRITE ORIGINAL XML)
write_xml(new_xml, paste0("new_", xml_file))
return(new_xml)
}
# ITERATE THROUGH XML FILES
new_xmls <- lapply(xmls, proc_xml)
I need a help in solving an issue with Xquery.
I am using below Xquery to get the "value" of attributes. However there is one attribute "Email" which has further child attributes. SO with below Xquery I am getting data for all the "Value"
i.e. truetruebc#hghh.gff, truetruexyn#qwe.com, 39919741
However I need only "abc#hghh.gff $# xyn#qwe.com, 39919741" in my output.
{/root/*/attributes/* [ov='true']/fn:concat(fn:data(value),',')}
<root>
<_1>
<attributes>
<Email>
<ov>true</ov>
<value>
<Email>
<ov>true</ov>
<value>abc#hghh.gff</value>
</Email>
</value>
</Email>
<Email>
<ov>true</ov>
<value>
<Email>
<ov>true</ov>
<value>xyn#qwe.com</value>
</Email>
</value>
</Email>
<UniqueId>
<ov>true</ov>
<value>39919741</value>
</UniqueId>
</attributes>
</_1>
</root>
I think you want to take the concatenation of those value descendant elements that don't have any child elements so you can use e.g. string-join(/root/*/attributes/*[ov='true']//value[not(*)], ',').
In XQuery 3.1 you could also use the innermost() function with e.g. string-join(innermost(/root/*/attributes/*[ov='true']//value), ',').
Try:
fn:string-join(/root/attributes[ov='true']/*/Value/string(), ",")
Your XML document isn't well-formed. (XML element names are case-sensitive, so you can't start with <Value> and end with <value>, for example.) So I fixed that.
Then, I found that your query yields nothing, because it's looking for an element ('*') between root and attributes, which doesn't exist in the document. So I changed /*/ to just /.
At that point, I got the result of ENtity1_Value, ENtity2_Value, ENtity3_Value,. So who knows where ChildValue1, ChildValue2, came from. Possibly your real query had a // in it.
(When you ask a question on StackOverflow, you should ensure that your example behaves as described.)
here is my sample XML :
<Entries>
<Entry>
<id>1</id>
.
.
</Entry>
<Entry>
<id>2</id>
<assets>
<TextAssetInfo>
<Name>Alpha</Name>
<TagName>alphaName</TagName>
<value>Harambe</value>
</TextAssetInfo>
</assets>
</Entry>
<Entries>
So my goal is simply to extract the value of Alpha and store it in a variable in my XSLT for further computation.
I am able extract and print the value. But not assign in to a variable.
Following part of XSL code works:
<T_AlphaName><xsl:value-of select="./assets/*[TagName = 'alphaName']/value"/></T_AlphaName>
However, I can't get the below to work :
<xsl:variable name="myVar" select="./assets/*[TagName = 'alphaName']/value"/>
I have tried many other combinations as well but no luck. What am I doing wrong? In my XSL I have part to test it and get a weird result
<TestVar><xsl:value-of select="$myVar"/></TestVar>
Result : <TestVar/>
Additional info :
Using XML/XSL version 1.0.
AlphaName is not the only TextAssetInfo inside the assets. There are many more.
I have a small problem - I have to list all the labels of several large shared projects, so labels that are missing a translation are identified updated.
Now what I'm looking is something like Palle Agermark's label export job (http://www.agermark.com/2011/10/export-and-import-labels-for.html) but one that goes through one or more projects and pulls all the label IDs (regardless of label series) and values for three languages to Excel.
Can this be done, any pointers? :)
This expands the idea of Jan B. Kjeldsen's last comment to get the labels from the project xpo file. The labels are saved in the xpo file in the following XML structure:
<Table:Record name="TmpSysLabel" xmlns:Table='urn:www.microsoft.com/Formats/Table'>
<Table:Field name="Language">de</Table:Field>
<Table:Field name="Label">Geplante Produktionsaufträge</Table:Field>
<Table:Field name="Description"></Table:Field>
<Table:Field name="LabelId">#SYS119128</Table:Field>
<Table:Field name="SysLabelApplModule">0</Table:Field>
<Table:Field name="recVersion">0</Table:Field>
<Table:Field name="Partition">5637144576</Table:Field>
</Table:Record>
My first idea was to import this XML to Excel, but Excel does not play nice with column names in attributes. So instead I wrote an xsl that transforms the XML into something like the following:
<?xml version="1.0" encoding="UTF-8"?>
<labels>
<record>
<Language>de</Language>
<Label>Geplante Produktionsaufträge</Label>
<Description />
<LabelId>#SYS119128</LabelId>
<SysLabelApplModule>0</SysLabelApplModule>
<recVersion>0</recVersion>
<Partition>5637144576</Partition>
</record>
</labels>
To do this transformation, the original XML has to be cleaned up a bit, replace all occurences of Table:Record with record and all occurences of Table:Field with field. Also add a root XML node labels. It should look like
<labels>
<record>
<field name="Language">de</field>
<field name="Label">Geplante Produktionsaufträge</field>
<field name="Description"></field>
<field name="LabelId">#SYS119128</field>
<field name="SysLabelApplModule">0</field>
<field name="recVersion">0</field>
<field name="Partition">5637144576</field>
</record>
</labels>
Now for the fun part (at least for me because I had not much prior knowledge of xsl syntax), the xsl transformation file. I ended up with the following, which will produce the wanted XML using http://www.freeformatter.com/xsl-transformer.html:
<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/">
<labels>
<xsl:for-each select="Labels/*">
<record>
<xsl:for-each select="*">
<xsl:element name="{#name}">
<xsl:value-of select="." />
</xsl:element>
</xsl:for-each>
</record>
</xsl:for-each>
</labels>
</xsl:template>
</xsl:stylesheet>
The resulting XML can then be imported into Excel using the Excel developer Tools for XML. The result will look like
The simplest solution would be to go to the label source directly.
In AX 2009 the labels are stored in the application folder and named like like axSYSen-us.ald with the following parts:
ax - the file prefix
SYS - the label name, #SYS123 labels are stored there
en-us - the language specifier
ald - the label file extension
The files are in text format and can easily be imported to Excel or edited with an text editor.
You could import to Excel, one sheet for each label file, then combine the output in a separate sheet (in the same workbook) using Excel formulas.
In AX 2012 the labels are stored in the model database and the .ald files are created on startup.
basically I want to put information into a balloon in Maps API, this is the KML file, the data is stored using SimpleData tags, and I am trying to access to it from the BalloonStyle text tag.
But it doesn't work, in the baloon is displayed simply $[something]. After some research, I discovered Entity replacement may not be supported anymore by SimpleData tags.
So how do I manage the data? I got the data from ogr2ogr conversion from a shapefile and I don't know how to manage its output to make it use ExtendedData and Data tags.
Thank for your help.
You can replace <SchemaData><SimpleData> with <Data><value> elements with a text editor preferably one that can perform regular expression replacements on searches such as NotePad++.
You start with this:
<ExtendedData>
<SchemaData schemaUrl="#biblioteche">
<SimpleData name="INDIRIZZO">VIA SAN VITTORE, 21</SimpleData>
<SimpleData name="TIPOLOGIA">BIBLIOTECHE</SimpleData>
...
<SimpleData name="ID">0</SimpleData>
</SchemaData>
</ExtendedData>
And need to convert to this form:
<ExtendedData>
<Data name="INDIRIZZO">
<value>VIA SAN VITTORE, 21</value>
</Data>
<Data name="TIPOLOGIA">
<value>BIBLIOTECHE</value>
</Data>
...
<Data name="ID">
<value>0</value>
</Data>
</ExtendedData>
Globally make the following replacements (in this order):
#
Find what
Replace with
1.
<SchemaData schemaUrl="#biblioteche">
2.
</SchemaData>
3.
<SimpleData
<Data
4.
(<Data name=".*?">)
\1<value>
5.
</SimpleData>
</value></Data>
Steps 1 and 2 have an empty target such that you delete the element.
Step 4 is the only step that needs to be done as a regular expression.
working example