Editing XML files - batch-file

I have some XML files and I need to edit them automatically.
For example
<Content>
<Texts>
<Text id="1">
<en value="blaabla" />
</Text>
<Text id="2">
<en value="blablablablal" />
</Text>
</Texts>
</Content>
I need to copy "en value" lines and add these lines to their under line but with one change.
So when processing done, result should be that:
<Content>
<Texts>
<Text id="1">
<en value="blablabla" />
<fr value="blablabla" />
</Text>
<Text id="2">
<en value="blablablablal" />
<fr value="blablablablal" />
</Text>
</Texts>
</Content>

You could use this XSLT to transform your XML files:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="en[#value]">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
<fr value="{#value}"/>
</xsl:template>
</xsl:stylesheet>

$ sed '/<en /p' data.txt | awk '/<en /{if(x++%2)sub(/<en /, "<fr ")}1'
<Content>
<Texts>
<Text id="1">
<en value="blaabla" />
<fr value="blaabla" />
</Text>
<Text id="2">
<en value="blablablablal" />
<fr value="blablablablal" />
using sed to duplicate line which contains <en
using awk to change the odd <en to <fr
WARNING: <en ... /> must be one line.

Related

Update XML stored in a XML column in SQL Server Update

Set Url value by applying filter based on location-type value from given sample.
<page id="{Page_ID}" name="" type="dat" size="0" sequence="26" originalpagenumber="26" location_type="3" location="">
<content description="" content_format="26" />
<AdditionalInfo>
<Url>https://s3-eu-west-1/2019/may//001063/gvb140/683c82a3-b3f5-49ee-a34e-01859e8e2228.mp3</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
The XML you've shared is invalid so I've taken the liberty to make it valid in an effort to show you how I might approach this.
I've made the assumption you're looking to update values in a table somewhere in your environment. You can run this example in SSMS.
THIS IS MEANT AS AN EXAMPLE ONLY. DO NOT BLINDLY RUN THIS AGAINST PRODUCTION DATA.
First, I created a mock-up table that holds some page XML data. I assumed that a single XML row could contain multiple page nodes with duplicate location_type values.
DECLARE #Pages TABLE ( page_xml XML );
INSERT INTO #Pages ( page_xml ) VALUES (
'<pages>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="26" originalpagenumber="26" location_type="3" location="">
<content description="" content_format="26" />
<AdditionalInfo>
<Url>https://s3-eu-west-1/2019/may//001063/gvb140/683c82a3-b3f5-49ee-a34e-01859e8e2228.mp3</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="27" originalpagenumber="27" location_type="3" location="">
<content description="" content_format="27" />
<AdditionalInfo>
<Url>https://s3-eu-west-1/2019/may//001063/gvb140/683c82a3-b3f5-49ee-a34e-01859e8e2228.mp3</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="28" originalpagenumber="28" location_type="8" location="">
<content description="" content_format="28" />
<AdditionalInfo>
<Url>https://s3-eu-west-1/2019/may//001063/gvb140/683c82a3-b3f5-49ee-a34e-01859e8e2228.mp3</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
</pages>' );
Selecting the current results from #Pages shows the following XML:
<pages>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="26" originalpagenumber="26" location_type="3" location="">
<content description="" content_format="26" />
<AdditionalInfo>
<Url>https://s3-eu-west-1/2019/may//001063/gvb140/683c82a3-b3f5-49ee-a34e-01859e8e2228.mp3</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="27" originalpagenumber="27" location_type="3" location="">
<content description="" content_format="27" />
<AdditionalInfo>
<Url>https://s3-eu-west-1/2019/may//001063/gvb140/683c82a3-b3f5-49ee-a34e-01859e8e2228.mp3</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="28" originalpagenumber="28" location_type="8" location="">
<content description="" content_format="28" />
<AdditionalInfo>
<Url>https://s3-eu-west-1/2019/may//001063/gvb140/683c82a3-b3f5-49ee-a34e-01859e8e2228.mp3</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
</pages>
There are two pages with a location_type of 3, and one with a location_type of 8.
Next, I declared a few variables which I then used to modify the XML.
DECLARE #type INT = 3, #url VARCHAR(255) = 'http://www.google.com';
/* Update each Url text for the specified location_type */
WHILE EXISTS ( SELECT * FROM #Pages WHERE page_xml.exist( '//pages/page[#location_type=sql:variable("#type")]/AdditionalInfo/Url[text()!=sql:variable("#url")]' ) = 1 )
UPDATE #Pages
SET
page_xml.modify( '
replace value of (//pages/page[#location_type=sql:variable("#type")]/AdditionalInfo/Url/text()[.!=sql:variable("#url")])[1]
with sql:variable("#url")
' );
After running the update the XML now contains:
<pages>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="26" originalpagenumber="26" location_type="3" location="">
<content description="" content_format="26" />
<AdditionalInfo>
<Url>http://www.google.com</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="27" originalpagenumber="27" location_type="3" location="">
<content description="" content_format="27" />
<AdditionalInfo>
<Url>http://www.google.com</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
<page id="{Page_ID}" name="" type="dat" size="0" sequence="28" originalpagenumber="28" location_type="8" location="">
<content description="" content_format="28" />
<AdditionalInfo>
<Url>https://s3-eu-west-1/2019/may//001063/gvb140/683c82a3-b3f5-49ee-a34e-01859e8e2228.mp3</Url>
<Name />
<Encoding>audio</Encoding>
<SecurityType>IBCloud</SecurityType>
</AdditionalInfo>
</page>
</pages>
Using the WHILE EXISTS (... ensures that all Url nodes for the requested location_type are updated. In my example here there are two pages with a value of 3 that are updated, while location_type 8 is left alone.
Basically, what this is doing is updating the Url for any page with the requested location_type to the new #url value.
There are two key pieces here, the first being:
.exist( '//pages/page[#location_type=sql:variable("#type")]/AdditionalInfo/Url[text()!=sql:variable("#url")]' )
Which looks for the requested location_type that doesn't have the new #url value.
And the second:
page_xml.modify( '
replace value of (//pages/page[#location_type=sql:variable("#type")]/AdditionalInfo/Url/text()[.!=sql:variable("#url")])[1]
with sql:variable("#url")
' );
Which modifies (updates) the Url for the location type that has yet to be updated. The two "conditions" allow for a loop (WHILE) that ends when they're no longer met, ensuring that all page nodes for the requested location_type are updated.

How can I find and update a node attribute value in an XML document based on match of a different attribute value in the same node?

Given my T-SQL stored procedure with:
Declare #SearchID varchar(35)
Set #SearchID = '5280301.2019050148902.00023'
Declare #DocListXML XML
Contains the following XML data
<JobList ListItems="7">
<Job JobFriendlyName="EMAIL INVOICES">
<DocumentList>
<Document Doc="1" ID="5280301.2019050148902.00020" Date="05-03-2019" Status="NEW" />
<Document Doc="2" ID="5280301.2019050148902.00022" Date="05-03-2019" Status="NEW" />
<Document Doc="3" ID="5280301.2019050148902.00023" Date="05-03-2019" Status="NEW" />
<Document Doc="4" ID="5280301.2019050104301.00055" Date="05-02-2019" Status="NEW" />
<Document Doc="5" ID="5280301.2019050104301.00056" Date="05-02-2019" Status="NEW" />
</DocumentList>
</Job>
<Job JobFriendlyName="INVOICES">
<DocumentList>
<Document Doc="6" ID="5280300.2019050148901.00001" Date="05-03-2019" Status="NEW" />
<Document Doc="7" ID="5280300.2019050148901.00002" Date="05-03-2019" Status="NEW" />
</DocumentList>
</Job>
</JobList>
I need T-SQL XML code to update this document and replace existing Status value with "OLD" for the node having ID attribute value matching the value of T-SQL local variable #SearchID.
After the update, the resulting document in #DocListXML should contain:
<JobList ListItems="7">
<Job JobFriendlyName="EMAIL INVOICES">
<DocumentList>
<Document Doc="1" ID="5280301.2019050148902.00020" Date="05-03-2019" Status="NEW" />
<Document Doc="2" ID="5280301.2019050148902.00022" Date="05-03-2019" Status="NEW" />
<Document Doc="3" ID="5280301.2019050148902.00023" Date="05-03-2019" Status="OLD" />
<Document Doc="4" ID="5280301.2019050104301.00055" Date="05-02-2019" Status="NEW" />
<Document Doc="5" ID="5280301.2019050104301.00056" Date="05-02-2019" Status="NEW" />
</DocumentList>
</Job>
<Job JobFriendlyName="INVOICES">
<DocumentList>
<Document Doc="6" ID="5280300.2019050148901.00001" Date="05-03-2019" Status="NEW" />
<Document Doc="7" ID="5280300.2019050148901.00002" Date="05-03-2019" Status="NEW" />
</DocumentList>
</Job>
</JobList>
I have found the modify/replace code to modify an attribute value of "X" "Y", but cannot find code for modify/update updating attribute [a] value in node with attribute [b] value matching a local variable.
Any help or suggestions would be appreciated.
Okay, after your last question you decided to got the CURSOR route, correct? ;-)
Try it like this.
--Your mockup up
Declare #SearchID varchar(35) = '5280301.2019050148902.00023';
Declare #DocListXML XML=
N'<JobList ListItems="7">
<Job JobFriendlyName="EMAIL INVOICES">
<DocumentList>
<Document Doc="1" ID="5280301.2019050148902.00020" Date="05-03-2019" Status="NEW" />
<Document Doc="2" ID="5280301.2019050148902.00022" Date="05-03-2019" Status="NEW" />
<Document Doc="3" ID="5280301.2019050148902.00023" Date="05-03-2019" Status="NEW" />
<Document Doc="4" ID="5280301.2019050104301.00055" Date="05-02-2019" Status="NEW" />
<Document Doc="5" ID="5280301.2019050104301.00056" Date="05-02-2019" Status="NEW" />
</DocumentList>
</Job>
<Job JobFriendlyName="INVOICES">
<DocumentList>
<Document Doc="6" ID="5280300.2019050148901.00001" Date="05-03-2019" Status="NEW" />
<Document Doc="7" ID="5280300.2019050148901.00002" Date="05-03-2019" Status="NEW" />
</DocumentList>
</Job>
</JobList>';
--This is the modifying command
SET #DocListXML.modify(N'replace value of (/JobList
/Job
/DocumentList
/Document[#ID=sql:variable("#SearchID")]
/#Status)[1] with "OLD"');
--check the result
SELECT #DocListXML;
Hint 1: This works only in cases where there is just one document with the given ID per XML!
Hint 2: You might shorten the command to this:
SET #DocListXML.modify(N'replace value of (//Document[#ID=sql:variable("#SearchID")]/#Status)[1] with "OLD"');
The deep search (triggered by the double slash // at the beginning of the XPath) tells the engine to find a <Document> fullfilling the predicate anywhere in your XML.

Parsing XML in T-SQL - ABS data

I'm after some assistance parsing an xml file provided by the Australian Bureau of Statistics. I've read over everything I can find here and online, and am not having much luck reading this data.
This is a sample of the XML:
<?xml version='1.0' encoding='UTF-8'?>
<message:MessageGroup xmlns:message="http://www.w3.org/2001/XMLSchema" xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic" xmlns:common="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic http://www.sdmx.org/docs/2_0/SDMXGenericData.xsd http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message http://www.sdmx.org/docs/2_0/SDMXMessage.xsd">
<Header xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message">
<ID>none</ID>
<Test>false</Test>
<Truncated>false</Truncated>
<Prepared>2018-02-14T22:41:03</Prepared>
<Sender id="ABS">
<Name xml:lang="en">Australian Bureau of Statistics</Name>
<Name xml:lang="fr">Australian Bureau of Statistics</Name>
</Sender>
</Header>
<DataSet keyFamilyURI="http://stat.data.abs.gov.au/restsdmx/sdmx.ashx/GetKeyFamily/RES_PROP_INDEX">
<KeyFamilyRef>RES_PROP_INDEX</KeyFamilyRef>
<Series>
<SeriesKey>
<Value concept="MEASURE" value="1" />
<Value concept="PROP_TYPE" value="3" />
<Value concept="ASGS_2011" value="3GBRI" />
<Value concept="FREQUENCY" value="Q" />
</SeriesKey>
<Attributes>
<Value concept="TIME_FORMAT" value="P3M" />
</Attributes>
<Obs>
<Time>2015-Q1</Time>
<ObsValue value="112.7" />
</Obs>
<Obs>
<Time>2015-Q2</Time>
<ObsValue value="113.7" />
</Obs>
</Series>
<Series>
<SeriesKey>
<Value concept="MEASURE" value="1" />
<Value concept="PROP_TYPE" value="3" />
<Value concept="ASGS_2011" value="5GPER" />
<Value concept="FREQUENCY" value="Q" />
</SeriesKey>
<Attributes>
<Value concept="TIME_FORMAT" value="P3M" />
</Attributes>
<Obs>
<Time>2015-Q1</Time>
<ObsValue value="114.4" />
</Obs>
<Obs>
<Time>2015-Q2</Time>
<ObsValue value="113.4" />
</Obs>
</Series>
<Annotations>
<common:Annotation>
<common:AnnotationTitle>Statistical usage warning</common:AnnotationTitle>
<common:AnnotationText>ABS.Stat beta is continuing to be developed. Data will be updated as soon as possible following its 11:30 am release on the ABS website.</common:AnnotationText>
</common:Annotation>
</Annotations>
</DataSet>
</message:MessageGroup>
The result set should return 3 values:
SeriesKey Value where Concept = 'ASGS_2011'
Obs "Time" Value
Obs "Obsvalue" Value
e.g the first record would return a row like:
3GBRI | 2015-Q1 | 112.7
This sample would return 4 rows of data like this.
I've tried inserting the XML into an XML variable or a column in a DB with an XML datatype, and then using SQL's XML functionality, but I'm an absolute novice at this and am having trouble with the correct coding/approach.
Any advice or sample code would be greatly appreciated.
I'd suggest do get rid of the <?xml blah ?> declaration. This is only useful when you store an XML to a file. Within SQL-Server any XML's encoding is fixed to unicode / UCS-2. This can lead to encoding problems...
There are namespaces involved...
DECLARE #xml XML=
'<?xml version=''1.0'' encoding=''UTF-8''?>
<message:MessageGroup xmlns:message="http://www.w3.org/2001/XMLSchema" xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic" xmlns:common="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic http://www.sdmx.org/docs/2_0/SDMXGenericData.xsd http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message http://www.sdmx.org/docs/2_0/SDMXMessage.xsd">
<Header xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message">
<ID>none</ID>
<Test>false</Test>
<Truncated>false</Truncated>
<Prepared>2018-02-14T22:41:03</Prepared>
<Sender id="ABS">
<Name xml:lang="en">Australian Bureau of Statistics</Name>
<Name xml:lang="fr">Australian Bureau of Statistics</Name>
</Sender>
</Header>
<DataSet keyFamilyURI="http://stat.data.abs.gov.au/restsdmx/sdmx.ashx/GetKeyFamily/RES_PROP_INDEX">
<KeyFamilyRef>RES_PROP_INDEX</KeyFamilyRef>
<Series>
<SeriesKey>
<Value concept="MEASURE" value="1" />
<Value concept="PROP_TYPE" value="3" />
<Value concept="ASGS_2011" value="3GBRI" />
<Value concept="FREQUENCY" value="Q" />
</SeriesKey>
<Attributes>
<Value concept="TIME_FORMAT" value="P3M" />
</Attributes>
<Obs>
<Time>2015-Q1</Time>
<ObsValue value="112.7" />
</Obs>
<Obs>
<Time>2015-Q2</Time>
<ObsValue value="113.7" />
</Obs>
</Series>
<Series>
<SeriesKey>
<Value concept="MEASURE" value="1" />
<Value concept="PROP_TYPE" value="3" />
<Value concept="ASGS_2011" value="5GPER" />
<Value concept="FREQUENCY" value="Q" />
</SeriesKey>
<Attributes>
<Value concept="TIME_FORMAT" value="P3M" />
</Attributes>
<Obs>
<Time>2015-Q1</Time>
<ObsValue value="114.4" />
</Obs>
<Obs>
<Time>2015-Q2</Time>
<ObsValue value="113.4" />
</Obs>
</Series>
<Annotations>
<common:Annotation>
<common:AnnotationTitle>Statistical usage warning</common:AnnotationTitle>
<common:AnnotationText>ABS.Stat beta is continuing to be developed. Data will be updated as soon as possible following its 11:30 am release on the ABS website.</common:AnnotationText>
</common:Annotation>
</Annotations>
</DataSet>
</message:MessageGroup>';
--The query will declare the needed namespaces and then use .nodes() to get the <Series> and a second call to .nodes() to get the nested <Obs>:
WITH XMLNAMESPACES(DEFAULT 'http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic'
,'http://www.w3.org/2001/XMLSchema' AS message)
SELECT ser.value(N'(SeriesKey/Value[#concept="ASGS_2011"]/#value)[1]',N'nvarchar(max)') AS Concept
,obs.value(N'(Time/text())[1]',N'nvarchar(max)') AS [Time]
,obs.value(N'(ObsValue/#value)[1]',N'decimal(10,4)') AS ObsValue
FROM #xml.nodes(N'/message:MessageGroup/DataSet/Series') AS A(ser)
OUTER APPLY A.ser.nodes(N'Obs') AS B(obs);
The result
Concept Time ObsValue
3GBRI 2015-Q1 112.7000
3GBRI 2015-Q2 113.7000
5GPER 2015-Q1 114.4000
5GPER 2015-Q2 113.4000

X3Dom set ImageTexture in Text

I have this code and it doesn't work. How can I fix it?
And how can I change the size of text?
<x3d width='800px' height='400px'>
<scene>
<shape>
<Appearance>
<ImageTexture url='1.jpg'/>
</Appearance>
<Text string='3'>
<FontStyle style='BOLD' />
</Text>
</shape>
</scene>
You cannot set a font size on a ImageTexture. Anyways, here's an example of creating a textured cube (Box) and putting a Text shape in front of it.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D>
<Scene>
<Group>
<Transform>
<Shape>
<Appearance>
<ImageTexture url='1.jpg'/>
</Appearance>
<Box/>
</Shape>
<Transform translation="0 0 1">
<Shape>
<Appearance>
<Material/>
</Appearance>
<Text string='"This is a text"'>
<FontStyle family='"SANS"' justify='"MIDDLE"' size="1.5" style="BOLD"/>
</Text>
</Shape>
</Transform>
</Transform>
</Group>
</Scene>
</X3D>

AEM 6: xtype tabpanel unable to change the dimension

Is it even possible to change the dimension of a tabpanel. I tried height and width but it's not working. Any pointers.
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:Dialog"
height="{Long}600"
title="Tiles"
width="{Long}850"
xtype="tabpanel">
<items jcr:primaryType="cq:WidgetCollection">
</items>
</jcr:root>
Thanks
Change the xtype on cq:Dialog to "dialog", and move the tabpanel 2 levels down, i.e.:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:Dialog"
height="650"
title="Tiles"
width="850"
xtype="dialog">
<items jcr:primaryType="cq:WidgetCollection">
<tabpanel
jcr:primaryType="cq:Widget"
xtype="tabpanel">
<items jcr:primaryType="cq:WidgetCollection">
...
</items>
</tabpanel>
</items>
</jcr:root>
I have implemented the following structure and it works perfectly:
- cq:Dialog
- cq:WidgetCollection
- cq:TabPanel
- cq:WidgetCollection
- cq:Widget
- cq:Widget
...
as real life example:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Dialog"
title="Filter Component"
height="{Long}500"
width="{Long}550"
xtype="dialog">
<items jcr:primaryType="cq:WidgetCollection">
<tabs jcr:primaryType="cq:TabPanel">
<items jcr:primaryType="cq:WidgetCollection">
<tab1 jcr:primaryType="cq:Widget"
... more attributes
/>
<tab2 jcr:primaryType="cq:Widget"
... more attributes
/>
</items>
</tabs>
</items>
</jcr:root>
NOTE: Both width and height attributes must be configured explicitly in the cq:Dialog node

Resources