I have this xml file:
<achievements>
<achievement id="1" name="Monster Slayer Lv1" description="Slay 15 monsters of any type" icon="Icon.skill0496" categoryId="1">
<conditions>
<condition name="Level" val="50" />
</conditions>
<items>
<item id="6393" count="1" />
</items>
</achievement>
<achievement id="2" name="Monster Slayer Lv2" description="Slay 50 monsters of any type" icon="Icon.skill0497" categoryId="1">
<conditions>
<condition name="MonsterKill" val="50" />
</conditions>
<items>
<item id="57" count="50000000" />
</items>
</achievement>
</achievements>
And i want my code:
try
{
final File inputFile = new File("C:/Users/ProjectX/Desktop/achievement.xml");
final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
final DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
final Document doc = dBuilder.parse(inputFile);
for (Node node = doc.getFirstChild().getFirstChild(); node != null; node = node.getNextSibling())
{
if (node.getNodeName().equalsIgnoreCase("achievements"))
{
for (Node ach_node = node.getFirstChild().getFirstChild(); ach_node != null; ach_node = ach_node.getNextSibling())
{
if (ach_node.getNodeName().equalsIgnoreCase("achievement"))
{
}
}
}
}
}
catch (final Exception e)
{
e.printStackTrace();
}
to read until achievement and delete all sub-node (which include all condition and items or any other child node it might have). In addition i want to replace with my own node such as"
<dropList id="x">
<itemId="x" min="x" max="x" chance="x" />
</dropList>
Anyone know how to do this? Thanks in advance a lot to all community member who spend their time reading this.
<achievements>
<achievement id="1" name="Monster Slayer Lv1" description="Slay 15 monsters of any type" icon="Icon.skill0496" categoryId="1">
<conditions>
<condition name="Level" val="50" />
</conditions>
<dropList id="1">
<itemId="x" min="x" max="x" chance="x" />
</dropList>
<dropList id="2">
<itemId="x" min="x" max="x" chance="x" />
</dropList>
</achievement>
<achievement id="2" name="Monster Slayer Lv2" description="Slay 50 monsters of any type" icon="Icon.skill0497" categoryId="1">
<conditions>
<condition name="MonsterKill" val="50" />
</conditions>
<dropList id="1">
<itemId="x" min="x" max="x" chance="x" />
</dropList>
<dropList id="2">
<itemId="x" min="x" max="x" chance="x" />
</dropList>
</achievement>
</achievements>
It is better to use an XSLT transformation for your case. It has a specific pattern for exactly what you need. It is called Identity Transform.
All you need to do is just to run the XSLT below in your Java code.
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="items">
<dropList id="1">
<item Id="x" min="x" max="x" chance="x"/>
</dropList>
<dropList id="2">
<item Id="x" min="x" max="x" chance="x"/>
</dropList>
</xsl:template>
</xsl:stylesheet>
Output
<achievements>
<achievement id="1" name="Monster Slayer Lv1" description="Slay 15 monsters of any type" icon="Icon.skill0496" categoryId="1">
<conditions>
<condition name="Level" val="50"/>
</conditions>
<dropList id="1">
<item Id="x" min="x" max="x" chance="x"/>
</dropList>
<dropList id="2">
<item Id="x" min="x" max="x" chance="x"/>
</dropList>
</achievement>
<achievement id="2" name="Monster Slayer Lv2" description="Slay 50 monsters of any type" icon="Icon.skill0497" categoryId="1">
<conditions>
<condition name="MonsterKill" val="50"/>
</conditions>
<dropList id="1">
<item Id="x" min="x" max="x" chance="x"/>
</dropList>
<dropList id="2">
<item Id="x" min="x" max="x" chance="x"/>
</dropList>
</achievement>
</achievements>
Related
Basically I need to move the contents of OrderRelease and Order into the OrderLine level ussing xsl.
Example input XML:
<OrderRelease EnterpriseCode="BRD" ReleaseNo="1234ABC" DocumentType="0001" SellerOrganizationCode="BU1" ShipNode="US1">
<Order OrderDate="2019-06-13T09:27:36-04:00" Action="CANCEL" OrderNo="1234ABC">
<Extn ExtnWMSOrderNumber="123ADS"/>
</Order>
<OrderLines>
<OrderLine Action="CANCEL" PrimeLineNo="1" SubLineNo="1" OrderedQty="5">
<Item ItemID="A" UnitOfMeasure="STD" ProductClass="NEW"/>
</OrderLine>
<OrderLine Action="" PrimeLineNo="2" SubLineNo="1" OrderedQty="10">
<Item ItemID="B" UnitOfMeasure="STD" ProductClass="NEW"/>
</OrderLine>
<OrderLine Action="CANCEL" PrimeLineNo="3" SubLineNo="1" OrderedQty="0">
<Item ItemID="C" UnitOfMeasure="STD" ProductClass="NEW"/>
</OrderLine>
</OrderLines>
</OrderRelease>
Example of XML post translation:
<OrderLines>
<OrderLine Action="CANCEL" PrimeLineNo="1" SubLineNo="1" OrderedQty="5" OrderDate="2019-06-13T09:27:36-04:00" OrderNo="1234ABC" EnterpriseCode="BRD" ReleaseNo="1234ABC" DocumentType="0001" SellerOrganizationCode="BU1" ShipNode="US1" AggregatorOrderId=”12345 >
<Item ItemID="A" UnitOfMeasure="STD" ProductClass="NEW"/>
</OrderLine>
<OrderLine Action="" PrimeLineNo="1" SubLineNo="1" OrderedQty="10" OrderDate="2019-06-13T09:27:36-04:00" OrderNo="1234ABC" EnterpriseCode="BRD" ReleaseNo="1234ABC" DocumentType="0001" SellerOrganizationCode="BU1" ShipNode="US1" AggregatorOrderId=”12345>
<Item ItemID="B" UnitOfMeasure="STD" ProductClass="NEW"/>
</OrderLine>
<OrderLine Action="CANCEL" PrimeLineNo="1" SubLineNo="1" OrderedQty="0" OrderDate="2019-06-13T09:27:36-04:00" OrderNo="1234ABC" EnterpriseCode="BRD" ReleaseNo="1234ABC" DocumentType="0001" SellerOrganizationCode="BU1" ShipNode="US1 AggregatorOrderId=”12345">
<Item ItemID="C" UnitOfMeasure="STD" ProductClass="NEW"/>
</OrderLine>
</OrderLines>
I used the following XSL but it removes all of the original OrderLine elements and also doesn't seem to do it for each OrderLine
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="OrderRelease">
<OrderLine>
<xsl:copy-of select="#*|OrderLine/#*" />
<xsl:apply-templates /><!-- optional -->
</OrderLine>
</xsl:template>
<xsl:template match="Order">
<xsl:copy-of select="#*|OrderLine/#*" />
<xsl:apply-templates /><!-- optional -->
</xsl:template>
<xsl:template match="Extn">
<xsl:copy-of select="#*|OrderLine/#*" />
<xsl:apply-templates /><!-- optional -->
</xsl:template>
<xsl:template match="OrderLine">
<xsl:copy-of select="#*|OrderLine/#*" />
</xsl:template>
</xsl:stylesheet>
Output of this is
<OrderLine EnterpriseCode="BRD"
ReleaseNo="1234ABC"
DocumentType="0001"
SellerOrganizationCode="BU1"
ShipNode="US1"
OrderDate="2019-06-13T09:27:36-04:00"
Action="CANCEL"
OrderNo="1234ABC"
ExtnWMSOrderNumber="123ADS"
PrimeLineNo="3"
SubLineNo="1"
OrderedQty="0"/>
You could do it this way.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="OrderLines">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="OrderLine">
<xsl:copy>
<xsl:copy-of select="#*"/> <!-- OrderLine attributes -->
<xsl:copy-of select="../../#*"/> <!-- OrderRelease attributes -->
<xsl:copy-of select="../../Order/#*"/> <!-- Order attributes -->
<xsl:attribute name="AggregatorOrderId">12345</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="Item">
<xsl:copy>
<xsl:copy-of select="#*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
See it working here : https://xsltfiddle.liberty-development.net/93nwMog
I want to append the elements inside to another xml with tag. I dont want to copy tag.
I am doing the following but it copies the node name () too.
NodeList itemsNodeList = inputDoc.getElementsByTagName("Sequence");
for (int i = 0; i < itemsNodeList.getLength(); i++) {
Node copiedNode = resultDoc.importNode(itemsNodeList.item(i), true);
resultRatingsBodyNode.appendChild(copiedNode);
}
These are the xmls I want to copy from (everything inside sequence tag)
xml1.xml
<?xml version="1.0" encoding="UTF-8"?>
<processes>
<process>
<body name="main">
<sequence>
<receive name="Receive1" createInstance="yes" />
<assign name="Assign1" />
<invoke name="Invoke1" />
<style>
<Font>someFont</Font>
</style>
<assign name="Assign2" />
<reply name="Reply1" />
</sequence>
</body>
</process>
</processes>
xml2.xml
<?xml version="1.0" encoding="UTF-8"?>
<processes>
<process>
<body name="main">
<sequence>
<receive name="Receive1" createInstance="yes" />
<assign name="Assign2" />
<invoke name="Invoke2" />
<style>
<Font>someFont1</Font>
</style>
<assign name="Assign3" />
<reply name="Reply2" />
</sequence>
</body>
</process>
</processes>
This is the xml I want to copy to (inside sequence tag>
blank.xml
<?xml version="1.0" encoding="UTF-8"?>
<processes>
<process>
<body name="main">
<sequence>
</sequence>
</body>
</process>
</processes>
This is what I am expecting
Result.xml
<?xml version="1.0" encoding="UTF-8"?>
<processes>
<process>
<body name="main">
<sequence>
<receive name="Receive1" createInstance="yes" />
<assign name="Assign1" />
<invoke name="Invoke1" />
<style>
<Font>someFont</Font>
</style>
<assign name="Assign2" />
<reply name="Reply1" />
<receive name="Receive2" createInstance="yes" />
<assign name="Assign2" />
<invoke name="Invoke2" />
<style>
<Font>someFont1</Font>
</style>
<assign name="Assign3" />
<reply name="Reply2" />
</sequence>
</body>
</process>
</processes>
UPDATE
If I have have follwing blank.xml how do I delete the elements in the sequence node before copying elements into it?
<?xml version="1.0" encoding="UTF-8"?>
<processes>
<process>
<body name="main">
<sequence>
<delete>Delete everthing between sequence tag before copying</delete>
</sequence>
</body>
</process>
</processes>
UPDATE 2
I am getting the following. I think it is deleting everything inside the node before copying.
<?xml version="1.0" encoding="UTF-8"?>
<processes>
<process>
<body name="main">
<sequence>
<receive name="Receive2" createInstance="yes" />
<assign name="Assign2" />
<invoke name="Invoke2" />
<style>
<Font>someFont1</Font>
</style>
<assign name="Assign3" />
<reply name="Reply2" />
</sequence>
</body>
</process>
</processes>
Process only the childNodes.
NodeList itemsNodeList = inputDoc.getElementsByTagName("sequence");
Node resultSequence= resultDoc.getElementsByTagName("sequence").item(0);
NodeList resultChildren=resultSequence.getChildNodes();
for(int i=0;i<resultChildren.getLength();i++) {
resultSequence.removeChild(resultChildren.item(i));
}
for (int i = 0; i < itemsNodeList.getLength(); i++) {
NodeList children=itemsNodeList.item(i).getChildNodes();
for(int j=0;j<children.getLength();j++) {
Node copiedNode = resultDoc.importNode(children.item(j), true);
resultSequence.appendChild(copiedNode);
}
}
We have to Parse a XML String
<GetTimetableEntriesResponse Result="Success">
<TimetableEntries>
<TimetableEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" order="1" TimetableEntryId="7645" TimetableEntryGroupId="1739" Name="Alm_04.jpg" Duration="7000">
<Template xsi:type="XmlImageTemplate" duration="7000">
<VerticalScroll>false</VerticalScroll>
<HorizontalScroll>false</HorizontalScroll>
<ScrollSpeed>50</ScrollSpeed>
<ScrollSpeedBack>100</ScrollSpeedBack>
<ScrollStartDelay>0</ScrollStartDelay>
<MediaItem id="6629" x="0" y="0" zIndex="0" type="jpg">
<width xsi:nil="true" />
<height xsi:nil="true" />
<rotation xsi:nil="true" />
<rotationcenterx xsi:nil="true" />
<rotationcentery xsi:nil="true" />
<alpha xsi:nil="true" />
<VerticalScroll xsi:nil="true" />
<HorizontalScroll xsi:nil="true" />
<ScrollSpeed xsi:nil="true" />
<ScrollSpeedBack xsi:nil="true" />
<ScrollStartDelay xsi:nil="true" />
<Loop xsi:nil="true" />
</MediaItem>
<Effect xsi:type="XmlFade" start="0" from="0" to="1" duration="500" />
<Effect xsi:type="XmlFade" start="6500" from="1" to="0" duration="500" />
<TemplateSource xsi:nil="true" />
</Template>
</TimetableEntry>
</GetTimetableEntriesResponse>
but <TimetableEntry> got no <Template> directly in it, programmatically it is handled in a Subclass called <TimetableData> which is in <TimetableEntry>
That means we handle it in java like :
<TimetableEntry>
<TimetableData>
<Template></Template>
</TimetableData>
</TimetableEntry>
We don't know how we should parse it in our Objects.
I trying transform (in eclipse) a document below:
<doc>
<city name="Paris"
country="France" />
<city name="Madrid"
country="Spain" />
<city name="Vienna"
country="Austria" />
<city name="Barcelona"
country="Spain" />
<city name="Salzburg"
country="Austria" />
<city name="Bonn"
country="Germany" />
<city name="Lyon"
country="France" />
<city name="Hannover"
country="Germany" />
<city name="Calais"
country="France" />
<city name="Berlin"
country="Germany" />
</doc>
with xslt:
<xsl:template match="/">
<out>
<all-countries>
<xsl:copy-of select="//city" />
</all-countries>
<distinct-countries>
<xsl:copy-of select="set:distinct(//#country/..)" />
</distinct-countries>
</out>
</xsl:template>
I'm use Xalan 2.7.1 it's work fine, but when I'm use 'JRE Instance Default' processor I get error:
16:07:20,642 ERROR [main] Main - java.lang.RuntimeException: Run-time internal error in 'HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted. '
This is guessing, but perhaps you can try other ways of getting the distinct values. Here are two suggestions, both of which are XSLT2.0 solutions:
<distinct-countries>
<xsl:copy-of select="distinct-values(//#country)" />
</distinct-countries>
<xsl:for-each-group select="//city" group-by="#country">
<xsl:value-of select="current-grouping-key()" />
</xsl:for-each-group>
If you are using XSLT1.0, the way to do this without using an extension function, it to make use of a technique called Muenchian Grouping. Firstly define a key to 'group' city elements by their country attribute.
<xsl:key name="countries" match="city" use="#country" />
Then you can pick out the distinct countries, by selecting the first city elements that occur in each group.
<distinct-countries>
<xsl:for-each select="//city[generate-id() = generate-id(key('countries', #country)[1])]">
<xsl:value-of select="#country" />
</xsl:for-each>
</distinct-countries>
How can I map the metadata to data. For example I only want LastName and Email from the xml file into the xls file. How can I select LastName and email from xml file and convert that into two column XLS file columns being Lastname and email. Thank you
XML Document
<root>
<metadata>
<item name="Last Name" type="xs:string" length="182"/>
<item name="First Name" type="xs:string" length="182"/>
<item name="Class Registration #" type="xs:decimal" precision="19"/>
<item name="Email" type="xs:string" length="422"/>
<item name="SacLink ID" type="xs:string" length="92"/>
<item name="Term Desc" type="xs:string" length="62"/>
<item name="Status Code" type="xs:string" length="6"/>
</metadata>
<data>
<row>
<value>XXX</value>
<value>xxxx</value>
<value>xxx</value>
<value>xxx</value>
<value>xxx</value>
<value>xx</value>
<value>xx</value>
</row>
<row>
<value>xxy</value>
<value>xx</value>
<value>xx</value>
<value>xx</value>
<value>xx</value>
<value>xx</value>
<value>xx</value>
</row>
</data>
</root>
You might use an XSL transform for this, outputting in CSV format which is loadable by Excel.
If you want to write a program using C# 4.0 and Office 2008/10, it's also easier than ever to leverage the interop capabilities - have a look at the C# Samples, in the office samples.
This stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:x="urn:schemas-microsoft-com:office:excel">
<xsl:param name="pColumnNames" select="'Last Name,Email'"/>
<xsl:key name="kItemByPosition" match="item"
use="count(preceding-sibling::item)+1"/>
<xsl:template match="/">
<xsl:processing-instruction name="mso-application">
<xsl:text>progid="Excel.Sheet"</xsl:text>
</xsl:processing-instruction>
<Workbook>
<Worksheet ss:Name="Email Table">
<Table x:FullColumns="1" x:FullRows="1">
<xsl:apply-templates/>
</Table>
</Worksheet>
</Workbook>
</xsl:template>
<xsl:template match="metadata|row">
<Row>
<xsl:apply-templates/>
</Row>
</xsl:template>
<xsl:template match="item|value">
<xsl:if test="contains(concat(',',$pColumnNames,','),
concat(',',key('kItemByPosition',
position())/#name,','))">
<Cell>
<Data ss:Type="String">
<xsl:apply-templates select="#name|node()"/>
</Data>
</Cell>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Output:
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:x="urn:schemas-microsoft-com:office:excel">
<Worksheet ss:Name="Email Table">
<Table x:FullColumns="1" x:FullRows="1">
<Row>
<Cell>
<Data ss:Type="String">Last Name</Data>
</Cell>
<Cell>
<Data ss:Type="String">Email</Data>
</Cell>
</Row>
<Row>
<Cell>
<Data ss:Type="String">XXX</Data>
</Cell>
<Cell>
<Data ss:Type="String">xxx</Data>
</Cell>
</Row>
<Row>
<Cell>
<Data ss:Type="String">xxy</Data>
</Cell>
<Cell>
<Data ss:Type="String">xx</Data>
</Cell>
</Row>
</Table>
</Worksheet>
</Workbook>