How to parse the below xml code? - java
I have sale tag as child node that exists for multiple times but in that Employee tag doesn't exists for all sale tag.need to parse this xml.Got Null pointer exception when there is no employee tag.How to parse this xml even if some child tag name doesn't exists?
<?xml version="1.0" encoding="ISO-8859-1"?>
<Transactions>
<DocumentInfo TransferType="Transactions" Copyright="2010, Hectronic GmbH" CreatedBy="HecPoll">
<CreateDate Year="2011" Month="7" Day="13"/>
<CreateTime Hour="6" Minute="0" Second="16"/>
</DocumentInfo>
<DocumentData>
<Sale RcpNum="151" Amount="228.760" Station="1" Customer="000003" Terminal="1">
<Date Year="2011" Month="07" Day="12"/>
<Time Hour="07" Minute="23" Second="00"/>
<ArticleSale Quantity="6.020" SglPriceAsSold="38.000" SglPriceAsStored="38.000" SglPrice="38.000" Amount="228.760" FCCAmount="228.760" Taxrate="18" LogicalFPNumber="1" TankNumber="3" ArtNum="3" SaleNum="1"/>
<Payment PAN="000000002117904490D" Amount="228.760" TenderCode="0" PayNum="1"/>
<Employee Lastname="V KALYANI"/>
<Vehicle LicensePlate="10K"/>
</Sale>
<Sale RcpNum="255" Amount="6650.000" Station="1" Customer="ZZZZZZ" Terminal="0">
<Date Year="2011" Month="07" Day="12"/>
<Time Hour="07" Minute="24" Second="00"/>
<ArticleSale Quantity="175.000" SglPriceAsSold="38.000" SglPriceAsStored="38.000" SglPrice="38.000" Amount="6650.000" FCCAmount="6650.000" Taxrate="19" LogicalFPNumber="1" TankNumber="1" ArtNum="3" SaleNum="1"/>
<Payment PAN="000000001885018677D" Amount="6650.000" TenderCode="0" PayNum="1"/>
</Sale>
<Sale RcpNum="152" Amount="3078.000" Station="1" Customer="000003" Terminal="1">
<Date Year="2011" Month="07" Day="12"/>
<Time Hour="07" Minute="27" Second="00"/>
<ArticleSale Quantity="81.000" SglPriceAsSold="38.000" SglPriceAsStored="38.000" SglPrice="38.000" Amount="3078.000" FCCAmount="3078.000" Taxrate="18" LogicalFPNumber="1" TankNumber="3" ArtNum="3" SaleNum="1"/>
<Payment PAN="000000002117928224D" Amount="3078.000" TenderCode="0" PayNum="1"/>
<Employee Lastname="A MUNIYANDI"/>
<Vehicle LicensePlate="10F"/>
</Sale>
</DocumentData>
</Transactions>
Thanks,
I assume you are using dom parser. If you are using getElementsByTagName() method, it will return null if no such element found. You better check for null for Employee tag.
Related
Unable to run the XSLT through JAVA and Empty result observed in output
I just want to fetch a piece of tags from XML file and I'm using it XSLT. XSLT: <xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/><xsl:template match="#*|node()"> <xsl:copy> <xsl:apply-templates select="#*|node()" /> </xsl:copy> </xsl:template> <xsl:strip-space elements="*"/> <xsl:template match="/testng-results"> <xsl:copy-of select="class/test-method[#status='PASS']"/> </xsl:template></xsl:stylesheet> Input.XML <?xml version="1.0" encoding="UTF-8"?> <testng-results skipped="0" failed="0" total="10" passed="10"> <class name="com.transfermoney.Transfer"> <test-method status="PASS" name="setParameter" is-config="true" duration-ms="4" started-at="2018-08-16T21:43:38Z" finished-at="2018-08-16T21:43:38Z"> <params> <param index="0"> <value> <![CDATA[org.testng.TestRunner#31c2affc]]> </value> </param> </params> <reporter-output> </reporter-output> </test-method> <!-- setParameter --> </class> <class name="com.transfermoney.Transfer"> <test-method status="FAIL" name="setSettlementFlag" is-config="true" duration-ms="5" started-at="2018-08-16T21:44:55Z" finished-at="2018-08-16T21:44:55Z"> <reporter-output> <line> <![CDATA[runSettlement Value Set :false]]> </line> </reporter-output> </test-method> setSettlementFlag </class> </testng-results> JAVA Code: public static void main(String[] args) throws Exception { String XML = fetchDataFrmXML(".//Test//testng-results_2.xml"); Transformer t = TransformerFactory.newInstance().newTransformer(new StreamSource(new File(".//Test//Cut.xslt"))); t.transform(new StreamSource(new StringReader(XML)), new StreamResult(new File(".//Test//Sample1.xml"))); } Expected Output: <test-method status="PASS" name="setParameter" is-config="true" duration-ms="4" started-at="2018-08-16T21:43:38Z" finished-at="2018-08-16T21:43:38Z"> <params> <param index="0"> <value> <![CDATA[runSettlement Value Set :false]]> </value> </param> </params> <reporter-output/> </test-method> FetchXML: public static String fetchDataFrmXML(String fileLocation) throws Exception { file = new File(fileLocation); fr = new FileReader(file); br = new BufferedReader(fr); String temp; String result = ""; while ((temp = br.readLine()) != null) { result += temp; } br.close(); return result; } I'm getting the empty sample1.xml file after I ran the JAVA class file. But if the same XSLT script I just run it through online editor it's giving an expected result. Is there any issue in my java file to execute the XSLT? please help me on this.
Your code works for me. The only things I changed were: declaring the variables used in your fetchDataFromXML() method Adding the missing space after version="1.0" in your stylesheet Changing the file names. I added the line System.err.println(t.getClass().getName()); to identify the XSLT engine used; the output was com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl You might like to do the same. Looking more carefully at the output, it displays the record with status="PASS", which is what the code is selecting, though you said you wanted the one that has status="FAIL". A note about your fetchDataFrmXML() method: it's incredibly inefficient to build up the content of a string by repeated string concatenation this way. Use a StringBuilder instead. (I once earned myself $10K in consultancy fees by pointing this mistake out to a client, who probably saved themselves $1m in hardware costs as a result).
Xml validation with xsl
i have been trying to validate xml through xslt for couple of hours. i have following xsl form for xml validation. every time i try to validate xml, i get following warnings below and empty currencyid attributes in xml are ignored and xml validate although its not. Does anyone has an idea why its ignored and validated ? <xsl:variable name="CurrencyCodeList" select="',AED,AFN,ALL,AMD,ANG,AOA,ARS,AUD,AWG,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BOV,BRL,BSD,BTN,BWP,BYR,BZD,CAD,CDF,CHE,CHF,CHW,CLF,CLP,CNY,COP,COU,CRC,CUC,CUP,CVE,CZK,DJF,DKK,DOP,DZD,EEK,EGP,ERN,ETB,EUR,FJD,FKP,GBP,GEL,GHS,GIP,GMD,GNF,GTQ,GWP,GYD,HKD,HNL,HRK,HTG,HUF,IDR,ILS,INR,IQD,IRR,ISK,JMD,JOD,JPY,KES,KGS,KHR,KMF,KPW,KRW,KWD,KYD,KZT,LAK,LBP,LKR,LRD,LSL,LTL,LVL,LYD,MAD,MAD,MDL,MGA,MKD,MMK,MNT,MOP,MRO,MUR,MVR,MWK,MXN,MXV,MYR,MZN,NAD,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SDG,SEK,SGD,SHP,SLL,SOS,SRD,STD,SVC,SYP,SZL,THB,TJS,TMT,TND,TOP,TRY,TTD,TWD,TZS,UAH,UGX,USD,USN,USS,UYI,UYU,UZS,VEF,VND,VUV,WST,XAF,XAG,XAU,XBA,XBB,XBC,XBD,XCD,XDR,XFU,XOF,XPD,XPF,XPF,XPF,XPT,XTS,XXX,YER,ZAR,ZMK,ZWL,'"/> <xsl:template match="//#currencyID" priority="1008" mode="M0"> <svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl" context="//#currencyID"/> <!--ASSERT --> <xsl:choose> <xsl:when test="contains($CurrencyCodeList, concat(',',.,','))"/> <xsl:otherwise> <svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl" test="contains($CurrencyCodeList, concat(',',.,','))"> <xsl:attribute name="location"> <xsl:apply-templates select="." mode="schematron-select-full-path"/> </xsl:attribute> <svrl:text>Geçersiz currencyID niteliği : '<xsl:text/> <xsl:value-of select="."/> <xsl:text/>'. Geçerli değerler için kod listesine bakınız.</svrl:text> </svrl:failed-assert> </xsl:otherwise> </xsl:choose> <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M0"/> Warning: on line 286 The preceding-sibling axis starting at a namespace node will never select anything Warning: on line 311 The preceding-sibling axis starting at a namespace node will never select anything Warning: on line 407 The child axis starting at an attribute node will never select anything Warning: on line 407 The child axis starting at an attribute node will never select anything Warning: on line 407 The child axis starting at an attribute node will never select anything Warning: on line 436 The child axis starting at an attribute node will never select anything Warning: on line 436 The child axis starting at an attribute node will never select anything Warning: on line 436 EDIT: actually i transformed schematron to xslt in order to test it also in xslt. given was schematron for validating. so actually i have to validate through given schematron files, sample xml and java code for validating. main schematron and other files have more rules and patterns. but i removed most of them for sample code and easily testing. everything is validated successfully except attributes in elements.( e.g currencyId attribute). im using UgliSch (Ugli Schematron Validator) for schematron validation. MainSchematron.xml: <?xml version="1.0" encoding="UTF-8"?> <sch:schema xmlns="http://purl.oclc.org/dsdl/schematron" xmlns:sch="http://purl.oclc.org/dsdl/schematron" xmlns:sh="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader" xmlns:ef="http://www.efatura.gov.tr/envelope-namespace"> <sch:include href="UBL-TR_Codelist.xml#codes"/> <sch:include href="UBL-TR_Common_Schematron.xml#abstracts"/> <sch:ns prefix="cbc" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" /> <sch:rule context="//cbc:CurrencyCode"> <sch:extends rule="GeneralCurrencyCodeCheck"/> </sch:rule> <sch:rule context="//#currencyID"> <sch:extends rule="GeneralCurrencyIDCheck"/> </sch:rule> </sch:schema> UBL-TR_Common_Schematron.xml: <sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" xmlns="http://purl.oclc.org/dsdl/schematron"> <sch:pattern name="AbstractRules" id="abstracts"> <sch:p>Pattern for storing abstract rules</sch:p> <!-- Rule to validate currencyID Genel --> <sch:rule abstract="true" id="GeneralCurrencyIDCheck"> <sch:assert test="contains($CurrencyCodeList, concat(',',.,','))">Geçersiz currencyID niteliği : '<sch:value-of select="."/>'. Geçerli değerler için kod listesine bakınız.</sch:assert> </sch:rule> </sch:pattern> </sch:schema> UBL-TR_Codelist.xml: <sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" xmlns="http://purl.oclc.org/dsdl/schematron"> <sch:pattern name="CodeList" id="codes"> <sch:let name="CurrencyCodeList" value="',AED,AFN,ALL,AMD,ANG,AOA,ARS,AUD,AWG,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BOV,BRL,BSD,BTN,BWP,BYR,BZD,CAD,CDF,CHE,CHF,CHW,CLF,CLP,CNY,COP,COU,CRC,CUC,CUP,CVE,CZK,DJF,DKK,DOP,DZD,EEK,EGP,ERN,ETB,EUR,FJD,FKP,GBP,GEL,GHS,GIP,GMD,GNF,GTQ,GWP,GYD,HKD,HNL,HRK,HTG,HUF,IDR,ILS,INR,IQD,IRR,ISK,JMD,JOD,JPY,KES,KGS,KHR,KMF,KPW,KRW,KWD,KYD,KZT,LAK,LBP,LKR,LRD,LSL,LTL,LVL,LYD,MAD,MAD,MDL,MGA,MKD,MMK,MNT,MOP,MRO,MUR,MVR,MWK,MXN,MXV,MYR,MZN,NAD,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SDG,SEK,SGD,SHP,SLL,SOS,SRD,STD,SVC,SYP,SZL,THB,TJS,TMT,TND,TOP,TRY,TTD,TWD,TZS,UAH,UGX,USD,USN,USS,UYI,UYU,UZS,VEF,VND,VUV,WST,XAF,XAG,XAU,XBA,XBB,XBC,XBD,XCD,XDR,XFU,XOF,XPD,XPF,XPF,XPF,XPT,XTS,XXX,YER,ZAR,ZMK,ZWL,'"/> </sch:pattern> </sch:schema> sample.xml: <sh:StandardBusinessDocument xsi:schemaLocation="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader PackageProxy_1_2.xsd" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:ef="http://www.efatura.gov.tr/package-namespace" xmlns:oa="http://www.openapplications.org/oagis/9" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:sh="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ns9="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:ns11="urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2" xmlns:ns3="http://www.hr-xml.org/3" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <sh:StandardBusinessDocumentHeader> <sh:HeaderVersion>1.0</sh:HeaderVersion> <sh:Sender> <sh:Identifier>urn:mail:defaultgb#xxx.com.tr</sh:Identifier> <sh:ContactInformation> <sh:Contact>xxx Kurumsal Bilgi Sistemleri A.Ş</sh:Contact> <sh:ContactTypeIdentifier>UNVAN</sh:ContactTypeIdentifier> </sh:ContactInformation> <sh:ContactInformation> <sh:Contact>8110120507</sh:Contact> <sh:ContactTypeIdentifier>VKN_TCKN</sh:ContactTypeIdentifier> </sh:ContactInformation> </sh:Sender> <sh:Receiver> <sh:Identifier>urn:mail:defaultpk#xxx.com.tr</sh:Identifier> <sh:ContactInformation> <sh:Contact>KAKAR KURUMSAL BİLGİSİSTEMLERİ LTD.ŞTİ. Test Kullanıcısı</sh:Contact> <sh:ContactTypeIdentifier>UNVAN</sh:ContactTypeIdentifier> </sh:ContactInformation> <sh:ContactInformation> <sh:Contact>4545552073</sh:Contact> <sh:ContactTypeIdentifier>VKN_TCKN</sh:ContactTypeIdentifier> </sh:ContactInformation> </sh:Receiver> <sh:DocumentIdentification> <sh:Standard>UBL-TR</sh:Standard> <sh:TypeVersion>1.2</sh:TypeVersion> <sh:InstanceIdentifier>bb583542-a81a-4b45-87d6-e90596101a41</sh:InstanceIdentifier> <sh:Type>SENDERENVELOPE</sh:Type> <sh:MultipleType>false</sh:MultipleType> <sh:CreationDateAndTime>2016-01-06T16:27:25.759+02:00</sh:CreationDateAndTime> </sh:DocumentIdentification> </sh:StandardBusinessDocumentHeader> <ef:Package> <Elements> <ElementType>INVOICE</ElementType> <ElementCount>1</ElementCount> <ElementList> <ns9:Invoice> <ext:UBLExtensions> <ext:UBLExtension> <ext:ExtensionContent> ... </ext:ExtensionContent> </ext:UBLExtension> </ext:UBLExtensions> <cbc:UBLVersionID>2.1</cbc:UBLVersionID> <cbc:CustomizationID>TR1.2</cbc:CustomizationID> <cbc:ProfileID>TICARIFATURA</cbc:ProfileID> <cbc:ID>PAZ2015000000012</cbc:ID> <cbc:CopyIndicator>false</cbc:CopyIndicator> <cbc:UUID>54b0dad2-e3a7-44ee-848a-cf7977000020</cbc:UUID> <cbc:IssueDate>2016-01-06</cbc:IssueDate> <cbc:InvoiceTypeCode>SATIS</cbc:InvoiceTypeCode> <cbc:DocumentCurrencyCode>TRY</cbc:DocumentCurrencyCode> <cbc:LineCountNumeric>0</cbc:LineCountNumeric> <cac:Signature> <cbc:ID schemeID="VKN_TCKN">8110120507</cbc:ID> <cac:SignatoryParty> <cbc:WebsiteURI>http://www.xxx.com.tr/</cbc:WebsiteURI> <cac:PartyIdentification> <cbc:ID schemeID="VKN">8110120507</cbc:ID> </cac:PartyIdentification> <cac:PartyName> <cbc:Name>xxx Kurumsal Bilgi Sistemleri A.Ş</cbc:Name> </cac:PartyName> <cac:PostalAddress> <cbc:StreetName>Besiktas Teknik Universitesi</cbc:StreetName> <cbc:BuildingNumber>150/1G</cbc:BuildingNumber> <cbc:CitySubdivisionName>Besıktas</cbc:CitySubdivisionName> <cbc:CityName>Istanbul</cbc:CityName> <cbc:PostalZone>06100</cbc:PostalZone> <cac:Country> <cbc:Name>Turkiye</cbc:Name> </cac:Country> </cac:PostalAddress> </cac:SignatoryParty> <cac:DigitalSignatureAttachment> <cac:ExternalReference> <cbc:URI>#Signature</cbc:URI> </cac:ExternalReference> </cac:DigitalSignatureAttachment> </cac:Signature> <cac:AccountingSupplierParty> <cac:Party> <cac:PartyIdentification> <cbc:ID schemeID="VKN">7221130507</cbc:ID> </cac:PartyIdentification> <cac:PartyName> <cbc:Name>KAKAR KURUMSAL LTD.ŞTİ.</cbc:Name> </cac:PartyName> <cac:PostalAddress> <cbc:Room/> <cbc:BuildingName/> <cbc:BuildingNumber/> <cbc:CitySubdivisionName>besiktas</cbc:CitySubdivisionName> <cbc:CityName>istanbul</cbc:CityName> <cbc:PostalZone/> <cac:Country> <cbc:Name>ALMANYA</cbc:Name> </cac:Country> </cac:PostalAddress> <cac:Contact> <cbc:Telephone/> <cbc:Telefax/> <cbc:ElectronicMail/> </cac:Contact> </cac:Party> </cac:AccountingSupplierParty> <cac:AccountingCustomerParty> <cac:Party> <cbc:WebsiteURI/> <cac:PartyIdentification> <cbc:ID schemeID="VKN">2535552073</cbc:ID> </cac:PartyIdentification> <cac:PartyName> <cbc:Name>KAKAR LTD.ŞTİ. Test Kullanıcısı</cbc:Name> </cac:PartyName> <cac:PostalAddress> <cbc:ID/> <cbc:Postbox/> <cbc:Room/> <cbc:StreetName/> <cbc:BlockName/> <cbc:BuildingName/> <cbc:BuildingNumber/> <cbc:CitySubdivisionName>besiktas</cbc:CitySubdivisionName> <cbc:CityName>istanbul</cbc:CityName> <cbc:PostalZone/> <cbc:Region/> <cbc:District/> <cac:Country> <cbc:Name>TÜRKİYE</cbc:Name> </cac:Country> </cac:PostalAddress> <cac:Contact> <cbc:Telephone/> <cbc:Telefax/> <cbc:ElectronicMail/> </cac:Contact> <cac:Person> <cbc:FirstName/> <cbc:FamilyName/> </cac:Person> </cac:Party> </cac:AccountingCustomerParty> <cac:TaxTotal> <cbc:TaxAmount currencyID="TRY">2.16</cbc:TaxAmount> <cac:TaxSubtotal> <cbc:TaxableAmount currencyID="asdasdasdasd">0</cbc:TaxableAmount> <cbc:TaxAmount currencyID="TRY">2.16</cbc:TaxAmount> <cbc:CalculationSequenceNumeric>0</cbc:CalculationSequenceNumeric> <cbc:Percent>18</cbc:Percent> <cac:TaxCategory> <cac:TaxScheme> <cbc:Name>KDV</cbc:Name> <cbc:TaxTypeCode>0015</cbc:TaxTypeCode> </cac:TaxScheme> </cac:TaxCategory> </cac:TaxSubtotal> </cac:TaxTotal> <cac:LegalMonetaryTotal> <cbc:LineExtensionAmount currencyID="TRY">12</cbc:LineExtensionAmount> <cbc:TaxExclusiveAmount currencyID="TRY">12</cbc:TaxExclusiveAmount> <cbc:TaxInclusiveAmount currencyID="TRY">14.16</cbc:TaxInclusiveAmount> <cbc:AllowanceTotalAmount currencyID="TRY">0</cbc:AllowanceTotalAmount> <cbc:PayableAmount currencyID="TRY">14.16</cbc:PayableAmount> </cac:LegalMonetaryTotal> <cac:InvoiceLine> <cbc:ID>1</cbc:ID> <cbc:InvoicedQuantity unitCode="NIU">1</cbc:InvoicedQuantity> <cbc:LineExtensionAmount currencyID="">12</cbc:LineExtensionAmount> <cac:AllowanceCharge> <cbc:ChargeIndicator>false</cbc:ChargeIndicator> <cbc:MultiplierFactorNumeric>0</cbc:MultiplierFactorNumeric> <cbc:Amount currencyID="">0</cbc:Amount> <cbc:BaseAmount currencyID="">0</cbc:BaseAmount> </cac:AllowanceCharge> <cac:TaxTotal> <cbc:TaxAmount currencyID="">2.16</cbc:TaxAmount> <cac:TaxSubtotal> <cbc:TaxableAmount currencyID="">0</cbc:TaxableAmount> <cbc:TaxAmount currencyID="">2.16</cbc:TaxAmount> <cbc:Percent>18</cbc:Percent> <cac:TaxCategory> <cac:TaxScheme> <cbc:Name>KDV</cbc:Name> <cbc:TaxTypeCode>0015</cbc:TaxTypeCode> </cac:TaxScheme> </cac:TaxCategory> </cac:TaxSubtotal> </cac:TaxTotal> <cac:Item> <cbc:Name>asdasd</cbc:Name> </cac:Item> <cac:Price> <cbc:PriceAmount currencyID="TRY">12</cbc:PriceAmount> </cac:Price> </cac:InvoiceLine> </ns9:Invoice> </ElementList> </Elements> </ef:Package> </sh:StandardBusinessDocument> java : try (InputStream ubl = getClass().getResourceAsStream("/schematrons/UBL-TR_Main_Schematron.xml");) { SchemaFactory schemaFactory = SchemaFactory.newInstance(XmlSchemaNsUris.SCHEMATRON_NS_URI); Schema schema = schemaFactory.newSchema(new StreamSource(ubl)); Validator validator = schema.newValidator(); validator.setErrorHandler(validationErrorHandler); validator.validate(new StringSource(new String(binary,"UTF-8"))); } catch (Exception e) { e.printStackTrace(); }
Split unsymmetrical XML into multiple XMLs
I have to split an unsymmetrical xml on 'Trade' element using java '<?xml version="1.0" encoding="UTF-8" standalone="no"?> <BookingRequest> <Id>1234</Id> <App>Pan</App> <Parties> <Party>1</Party> <Party>2</Party> </Parties> <Contract> <Trades> <Trade> <Detail>100</Detail> <Location> <Num>10001</Num> </Location> </Trade> <Trade> <Detail>101</Detail> <Location> <Num>10002</Num> </Location> </Trade> </Trades> </Contract> </BookingRequest> My requirement is post split there should be 2 files: FILE 1: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <BookingRequest> <Id>1234</Id> <App>Pan</App> <Parties> <Party>1</Party> <Party>2</Party> </Parties> <Contract> <Trades> <Trade> <Detail>100</Detail> <Location> <Num>10001</Num> </Location> </Trade> </Trades> </Contract> </BookingRequest> FILE 2: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <BookingRequest> <Id>1234</Id> <App>Pan</App> <Parties> <Party>1</Party> <Party>2</Party> </Parties> <Contract> <Trades> <Trade> <Detail>101</Detail> <Location> <Num>10002</Num> </Location> </Trade> </Trades> </Contract> </BookingRequest> Could someone help me in doing this kind of splitting (preferably using DOM/XPath and NOT XSLT)
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document doc = factory.newDocumentBuilder().parse("booking-request.xml"); Element bookingRequest = doc.getDocumentElement(); Element contract = (Element)bookingRequest.getElementsByTagName("Contract").item(0); Element trades = (Element)contract.getElementsByTagName("Trades").item(0); List<Element> tradeList = new ArrayList<Element>(); NodeList nodeList = trades.getElementsByTagName("Trade"); for(int i=0; i<nodeList.getLength(); i++) tradeList.add((Element)nodeList.item(i)); Transformer transformer = TransformerFactory.newInstance().newTransformer(); int i = 0; for(Element trade: tradeList){ // remove all children of <Trades> while(trades.getFirstChild()!=null) trades.removeChild(trades.getFirstChild()); trades.appendChild(doc.createTextNode("\n ")); trades.appendChild(trade); trades.appendChild(doc.createTextNode("\n ")); ++i; transformer.transform(new DOMSource(doc), new StreamResult(new File("trade"+i+".xml"))); }
How to parse unconventional XML files
I have the need to take what I consider an "unconventional" XML file that I get in and convert it into what I consider "conventional". The below XML examples have been "scrubbed" of proprietary names/values. Here is what the "unconventional" XML file looks like: <?xml version="1.0" encoding="UTF-8"?> <dataView name="document/aDocument" xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <dataItems> <dataItem name="item1" location="item1" dataItemType="Long"> <value xsi:type="xs:string">1</value> </dataItem> <dataItem name="item2" location="item.seconditem(some item).ref" dataItemType="String"> <value xsi:type="xs:string">ABC2DEF3</value> </dataItem> </dataItems> <dataRepeaters> <dataRepeater name="SomeLevel1" runtimeInfomration="SomeLevel11984371030"> <dataGroups> <dataGroup name="SomeLevel2" location="SomeLevel:(a level).thelevel" keyValue="SomeLevel119843710300" runtimeInformation="19843710300"> <dataItems> <dataItem name="someItem1" location="someLevel.aLevel(another item)" dataItemType="String"> <value xsi:type="xs:string">12345</value> </dataItem> <dataItem name="someItem2" location="someLevel.aLevel(another item2)" dataItemType="Integer"/> <dataItem name="someItem3" location="someLevel.aLevel(another item3)" dataItemType="ObjectReference"> <value xsi:type="xs:string">11:20012:3536</value> </dataItem> <dataItem name="someItem4" location="someLevel.aLevel(another item4)" dataItemType="String"/> <dataItem name="someItem5" location="someLevel.aLevel(another item5)" dataItemType="String"> <value xsi:type="xs:string">someItem5 Data</value> </dataItem> <dataItem name="someItem6" location="someLevel.aLevel(another item6)" dataItemType="CurrencyAmount"> <value xsi:type="xs:string">123456:USD</value> </dataItem> </dataItems> </dataGroup> <dataGroup name="SomeLevel3" keyValue="SomeLevel31984371030" runtimeInformation="1984371030"> <dataRepeaters> <dataRepeater name="SomeLevel4" runtimeInfomration="SomeLevel4"> <dataGroups> <dataGroup name="SomeLevel5" location="anotherLevel.level5(SomeLevel5):someLevel5" keyValue="SomeLevel51984371030-11521863690" runtimeInformation="1984371030-11521863690"> <dataItems> <dataItem name="someItem6" location="someLevel.aLevel(another item6)" dataItemType="BigDecimal"> <value xsi:type="xs:string">303.149</value> </dataItem> <dataItem name="someItem7" location="someLevel.aLevel(another item7)" dataItemType="CurrencyAmount"> <value xsi:type="xs:string">117:USD</value> </dataItem> <dataItem name="someItem8" location="someLevel.aLevel(another item8)" dataItemType="String"> <value xsi:type="xs:string">117.000000:USD</value> </dataItem> <dataItem name="someItem9" location="someLevel.aLevel(another item9)" dataItemType="CurrencyAmount"> <value xsi:type="xs:string">117:USD</value> </dataItem> </dataItems> <dataRepeaters> <dataRepeater name="SomeLevel6" runtimeInfomration="someLevel6"> <dataGroups/> </dataRepeater> </dataRepeaters> </dataGroup> <dataGroup name="SomeLevel7" location="anotherLevel.level5(SomeLevel7):someLevel7" keyValue="SomeLevel71984371030-11521863690" runtimeInformation="1984371030-11521863690"> <dataItems> <dataItem name="someItem10" location="someLevel.aLevel(another item10)" dataItemType="BigDecimal"> <value xsi:type="xs:string">292.741</value> </dataItem> <dataItem name="someItem11" location="someLevel.aLevel(another item11)" dataItemType="CurrencyAmount"> <value xsi:type="xs:string">165:USD</value> </dataItem> <dataItem name="someItem12" location="someLevel.aLevel(another item12)" dataItemType="String"> <value xsi:type="xs:string">165.000000:USD</value> </dataItem> <dataItem name="someItem13" location="someLevel.aLevel(another item13)" dataItemType="CurrencyAmount"> <value xsi:type="xs:string">165:USD</value> </dataItem> </dataItems> <dataRepeaters/> </dataGroup> <dataGroup name="SomeLevel8" location="anotherLevel.level5(SomeLevel8):someLevel8" keyValue="SomeLevel81984371030-11521863690" runtimeInformation="1984371030-11521863690"> <dataItems> <dataItem name="someItem14" location="someLevel.aLevel(another item14)" dataItemType="BigDecimal"> <value xsi:type="xs:string">369.075</value> </dataItem> <dataItem name="someItem15" location="someLevel.aLevel(another item15)" dataItemType="CurrencyAmount"> <value xsi:type="xs:string">598:USD</value> </dataItem> <dataItem name="someItem16" location="someLevel.aLevel(another item16)" dataItemType="String"> <value xsi:type="xs:string">598.000000:USD</value> </dataItem> </dataItems> <dataRepeaters> <dataRepeater name="SomeLevel9" runtimeInfomration="someLevel9"> <dataGroups> <dataGroup name="SomeLevel10" location="ownedAuto.AgreementActual(Liability).ConstantRole(Policy Form):policyForm" keyValue="aomeLevel101984371030-11521863690-115218636900" runtimeInformation="1984371030-11521863690-115218636900"> <dataItems> <dataItem name="someItem17" location="someLevel.aLevel(another item17)" dataItemType="String"> <value xsi:type="xs:string">Some Data | ABC 123</value> </dataItem> <dataItem name="someItem18" location="someLevel.aLevel(another item18)" dataItemType="Integer"> <value xsi:type="xs:string">2</value> </dataItem> </dataItems> </dataGroup> </dataGroups> </dataRepeater> <dataRepeater name="SomeLevel10" runtimeInfomration="someLevel11"> <dataGroups/> </dataRepeater> </dataRepeaters> </dataGroup> </dataGroups> </dataRepeater> </dataRepeaters> </dataGroup> </dataGroups> </dataRepeater> </dataRepeaters> </dataView> I am trying to convert it to something like this: <?xml version="1.0" encoding="UTF-8"?> <dataView name="document/aDocument" xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <item1>1</item1> <item2>ABC2DEF3</item2> <SomeLevel1> <SomeLevel2> <someItem1>12345f</someItem1> <someItem2></someItem2> <someItem3>11:20012:3536</someItem3> <someItem4>12345f</someItem4> <someItem5>someItem5 Data</someItem5> <someItem6>123456:USD</someItem6> </SomeLevel2> <SomeLevel3> <SomeLevel4> <SomeLevel5> <someItem7>303.149</someItem7> <someItem8>117:USD</someItem8> <someItem9>117.000000:USD</someItem9> <someItem10>117:USD</someItem10> <SomeLevel6></SomeLevel6> </SomeLevel5> <SomeLevel7> <someItem11>292.741</someItem11> <someItem12>165:USD</someItem12> <someItem13>165.000000:USD</someItem13> <someItem14>165:USD</someItem14> </SomeLevel7> <SomeLevel8> <someItem15>369.075</someItem15> <someItem16>598:USD</someItem16> <someItem17>598.000000:USD</someItem17> <SomeLevel9> <SomeLevel10> <someItem18>Some Data | ABC 123</someItem18> <someItem19>2</someItem19> </SomeLevel10> </SomeLevel9> <SomeLevel11></SomeLevel11> </SomeLevel8> </SomeLevel4> </SomeLevel3> </SomeLevel1> </dataView> So basically I am trying to take the "name" attribute and make it the XML node/tag and the value between the <value> node/tag and use it as the "value" for the XML node/tag. I have tried several different parsing/writing "routines" and the below two are the two that have gotten me the closest. So I'm leaving out the other ones as they would be just "noise". Here is what I have tried so far: private Document xmlDocument; public void convertXML() { xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader("DSExample.xml"))); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Node dsNode = xmlDocument.getDocumentElement(); xmlDocument = docBuilder.newDocument(); // Attempt 1: doSomethingDS(dsNode); // This will convert the XML but with NO nesting - creates example output 1 // Attempt 2: traverseDS(dsNode); // This will create an XML with ONLY the root dataItems - Don't know why - creates example output 2 } public void doSomethingDS(Node node) { System.out.println(node.getNodeName()); Element xmlElement = null; // This will be the "root" element/node "dataView": if(node.getNodeName() != null && node.getNodeName().equalsIgnoreCase("dataView")) { // Debugging: Print the node printNode(node); String nodeName = node.getNodeName().trim(); rootElement = xmlDocument.createElement(nodeName); mPreviousElement = rootElement; addAllAttributesToRootElement((Element) node, rootElement); xmlDocument.appendChild(rootElement); } else { // Debugging: Print the node printNode(node); // If has "name" property - create element/node if(node.getAttributes() != null && node.getAttributes().getNamedItem("name") != null) { xmlElement = createElement(xmlDocument, node); if(xmlElement !=null && xmlDocument.getFirstChild() != null) { xmlDocument.getFirstChild().appendChild(xmlElement); } } } NodeList nodeList = node.getChildNodes(); for(int i = 0; i < nodeList.getLength(); i++) { Node currentNode = nodeList.item(i); if(currentNode.getNodeType() == Node.ELEMENT_NODE) { // recursively call this method for all the children which are of type Element doSomethingDS(currentNode); } } } // End of doSomethingDS() public void traverseDS(Node parentNode) { // This will create an XML with ONLY the root dataItems - Don't know why. Element xmlElement = null; //**************************************************************** // This will be the "root" element/node "dataView": if(parentNode.getNodeName() != null && parentNode.getNodeName().equalsIgnoreCase("dataView")) { // Debugging: Print the node printNode(parentNode); String nodeName = parentNode.getNodeName().trim(); rootElement = xmlDocument.createElement(nodeName); mPreviousElement = rootElement; if(!isRootNodeSet) { mRootNode = parentNode; isRootNodeSet = true; } addAllAttributesToRootElement((Element) parentNode, rootElement); xmlDocument.appendChild(rootElement); // traverse children Node theNode = parentNode.getFirstChild(); if(theNode != null) { theNode = theNode.getNextSibling(); } else if (isRootNodeSet) { theNode = mRootNode.getNextSibling(); } traverseDS(theNode); } else { // traverse all nodes that belong to the parent for(Node theNode = parentNode.getFirstChild(); theNode != null; theNode = theNode.getNextSibling()) { // Debugging: Print the node printNode(theNode); // If has "name" property - create element/node if(theNode.getAttributes() != null && theNode.getAttributes().getNamedItem("name") != null) { // Create new Element/Node xmlElement = createElement(xmlDocument, theNode); if(xmlElement !=null && xmlDocument.getFirstChild() != null) { xmlDocument.getFirstChild().appendChild(xmlElement); } else { System.out.println(" not a node we wanted?"); } } // traverse children traverseDS(theNode); } } } // End of traverseDS() private Element createElement(Document aDoc, Node aNode) { Element xmlElement = null; String elementName = ""; NamedNodeMap dataNodeMap = aNode.getAttributes(); if(dataNodeMap != null && dataNodeMap.getNamedItem("name") != null) { elementName = dataNodeMap.getNamedItem("name").getTextContent(); xmlElement = aDoc.createElement(elementName); // if node = "dataItem" - walk node to get <value> node // Note: some "dataItem" nodes also have a <previousValue> node - what to do with these???? if(aNode.getNodeName() != null && aNode.getNodeName().equalsIgnoreCase("dataItem")) { // Walk Node to get <value> node NodeList childNodes = aNode.getChildNodes(); int childNodesLength = childNodes.getLength(); for(int x = 0; x < childNodesLength; x++) { Node childNode = childNodes.item(x); if(childNode.getNodeName() != null && childNode.getNodeName().equalsIgnoreCase("value")) { xmlElement.setTextContent(childNode.getTextContent()); break; } } } } return xmlElement; } // End of createElement() Example Output 1 (created by doSomethingDS()): <?xml version="1.0" encoding="UTF-8" standalone="no"?> <dataView xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="document/aDocument"> <item1>1</item1> <item2>ABC2DEF3</item2> <SomeLevel1/> <SomeLevel2/> <someItem1>12345</someItem1> <someItem2/> <someItem3>11:20012:3536</someItem3> <someItem4/> <someItem5>someItem5 Data</someItem5> <someItem6>123456:USD</someItem6> <SomeLevel3/> <SomeLevel4/> <SomeLevel5/> <someItem6>303.149</someItem6> <someItem7>117:USD</someItem7> <someItem8>117.000000:USD</someItem8> <someItem9>117:USD</someItem9> <SomeLevel6/> <SomeLevel7/> <someItem10>292.741</someItem10> <someItem11>165:USD</someItem11> <someItem12>165.000000:USD</someItem12> <someItem13>165:USD</someItem13> <SomeLevel8/> <someItem14>369.075</someItem14> <someItem15>598:USD</someItem15> <someItem16>598.000000:USD</someItem16> <SomeLevel9/> <SomeLevel10/> <someItem17>Some Data | ABC 123</someItem17> <someItem18>2</someItem18> <SomeLevel11/> </dataView> Example Output 2 (Created by traverseDS()): <?xml version="1.0" encoding="UTF-8" standalone="no"?> <dataView xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="document/aDocument"> <item1>1</item1> <item2>ABC2DEF3</item2> </dataView> Now here is that catch.... What I get is dynamic I could get a Mac truck one time and a Toyota the next or a mixture of the two. And the size of the XML I get could be small or large. So it's hard to just use XPath or directly go after specific elements as I don't know what I'll get. This is why I'm basically walking/traversing the DOM a node at a time to extract out just what is useable. So my question is: What am I doing wrong in my parsing/writing of the XML file to not get it to look like what I'm trying to get it to look like?
This is (almost) trivially easy with XSLT: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ds="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://component.mycompany.com/entity/ds" > <xsl:output indent="yes" /> <xsl:strip-space elements="*" /> <xsl:template match="ds:dataView" priority="1"> <xsl:copy> <xsl:apply-templates /> </xsl:copy> </xsl:template> <xsl:template match="ds:*[#name]"> <xsl:element name="{#name}"> <xsl:apply-templates /> </xsl:element> </xsl:template> <xsl:template match="text()"> <xsl:value-of select="normalize-space()" /> </xsl:template> </xsl:stylesheet> applied do your input, gives you: <dataView xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <item1>1</item1> <item2>ABC2DEF3</item2> <SomeLevel1> <SomeLevel2> <someItem1>12345</someItem1> <someItem2 /> <someItem3>11:20012:3536</someItem3> <someItem4 /> <someItem5>someItem5 Data</someItem5> <someItem6>123456:USD</someItem6> </SomeLevel2> <SomeLevel3> <SomeLevel4> <SomeLevel5> <someItem6>303.149</someItem6> <someItem7>117:USD</someItem7> <someItem8>117.000000:USD</someItem8> <someItem9>117:USD</someItem9> <SomeLevel6 /> </SomeLevel5> <SomeLevel7> <someItem10>292.741</someItem10> <someItem11>165:USD</someItem11> <someItem12>165.000000:USD</someItem12> <someItem13>165:USD</someItem13> </SomeLevel7> <SomeLevel8> <someItem14>369.075</someItem14> <someItem15>598:USD</someItem15> <someItem16>598.000000:USD</someItem16> <SomeLevel9> <SomeLevel10> <someItem17>Some Data | ABC 123</someItem17> <someItem18>2</someItem18> </SomeLevel10> </SomeLevel9> <SomeLevel10 /> </SomeLevel8> </SomeLevel4> </SomeLevel3> </SomeLevel1> </dataView> Notes: Having numbered element names (someItem1 thru someItem6) will come back and bite you, eventually. XML elements have a natural order (or you can have a "number" attribute), putting a counter into the name is bad and wrong. Take my advice and don't do that (*). To understand the solution here's a quick breakdown: XSLT processors run XML nodes through templates by finding the best match for the XML node at hand. The process starts with the root node. Since there is no template explicitly matching the root node (<xsl:template match="/">), a default rule kicks in: Output nothing, but find templates for the child nodes. The first (and only) child node is the document element (<ds:dataView>). The template #1 matches that node, tells the processor to copy it and process its children (<xsl:apply-templates />). Every element that has a #name is matched by template #2, which outputs an element with that name and again processes its children. Every other element (like those <value> nodes) is - in the absence of any matching template - processed according to the mentioned default rule. Text nodes are matched by template #3, which outputs their trimmed value. Additional notes: The expression in curly braces is called an attribute value template. The template priority="1" makes sure that this template is selected for the <ds:dataView> element, because the other one would match as well. Your result document still is in the "http://component.mycompany.com/entity/ds". This might or might not be correct. I suspect it's not correct, technically speaking, but you decide. (*) <xsl:element name="{translate(#name, '0123456789', '')}" would be one variant to lose the counters.
XSLT has been created exactly for a task like that. As long as your Source-XML (unconventional xml) is well-formed (correct xml-syntax) so that it can be read by a standard xml-parser like DOM, you can use that. It works like so: You create a xsl-template file that contains a declerative description how the source xml should be transformed into another format. The transformation itself is done by a XSL-Transformer. The xsl is also an xml-format, so it should be quit easy readable, as long as the transformation is not too complex. Here is explained how that can be implemented: http://docs.oracle.com/javase/tutorial/jaxp/xslt/transformingXML.html
How to ignore namespaces when selecting XML nodes with XPath
I saw that there is an option to ignore namespace xpathUtil.getObjectValue("//*[local-name() = 'object name']") is it possible to add more objetcs names for example <Schema xmlns:m...... Namespace="app" xmlns:d = .... <complexType Name = "Comp> <EntityType Name = "a"> <EntityType Name = "b"> </Schema> <Schema xmlns:m...... Namespace="app2" xmlns:d = .... <complexType Name = "Comp2> <EntityType Name = "a2"> <EntityType Name = "b2"> </Schema> is it possible to get the data of the attribute EntityType only for Schema= app ? ( meaning to get the result of a and b and not a2 and b2 )
Assuming that a complete version of your input file might look like this <?xml version="1.0" encoding="ISO-8859-1"?> <Schemas> <ns1:Schema xmlns:ns1="app1" > <ns1:complexType Name = "Comp1"> <ns1:EntityType Name = "a1"/> <ns1:EntityType Name = "b1"/> </ns1:complexType> </ns1:Schema> <ns2:Schema xmlns:ns2="app2"> <ns2:complexType Name = "Comp2"> <ns2:EntityType Name = "a2"/> <ns2:EntityType Name = "b2"/> </ns2:complexType> </ns2:Schema> </Schemas> the following XSLT shows how to filter the tags by the URI of the namespaceand the name of the namespace. <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" /> <xsl:variable name="ns_uri1" select="'app1'"/> <xsl:variable name="ns_uri2" select="'app2'"/> <xsl:variable name="ns_name1" select="'ns1'"/> <xsl:variable name="ns_name2" select="'ns2'"/> <xsl:template match="/Schemas"> <apps> <app1_selected_by_namespace_uri> <xsl:copy-of select="*[local-name(.) = 'Schema' and namespace-uri(.)=$ns_uri1]"/> </app1_selected_by_namespace_uri> <app2_selected_by_namespace_uri> <xsl:copy-of select="*[local-name(.) = 'Schema' and namespace-uri(.)=$ns_uri2]"/> </app2_selected_by_namespace_uri> <app1_selected_by_namespace_name> <xsl:copy-of select="*[name(.) = concat($ns_name1, ':Schema')]"/> </app1_selected_by_namespace_name> <app2_selected_by_namespace_name> <xsl:copy-of select="*[name(.) = concat($ns_name2, ':Schema')]"/> </app2_selected_by_namespace_name> </apps> </xsl:template> </xsl:stylesheet> yielding the following output document <?xml version="1.0" encoding="UTF-8"?> <apps> <app1_selected_by_namespace_uri> <ns1:Schema xmlns:ns1="app1"> <ns1:complexType Name="Comp1"> <ns1:EntityType Name="a1"/> <ns1:EntityType Name="b1"/> </ns1:complexType> </ns1:Schema> </app1_selected_by_namespace_uri> <app2_selected_by_namespace_uri> <ns2:Schema xmlns:ns2="app2"> <ns2:complexType Name="Comp2"> <ns2:EntityType Name="a2"/> <ns2:EntityType Name="b2"/> </ns2:complexType> </ns2:Schema> </app2_selected_by_namespace_uri> <app1_selected_by_namespace_name> <ns1:Schema xmlns:ns1="app1"> <ns1:complexType Name="Comp1"> <ns1:EntityType Name="a1"/> <ns1:EntityType Name="b1"/> </ns1:complexType> </ns1:Schema> </app1_selected_by_namespace_name> <app2_selected_by_namespace_name> <ns2:Schema xmlns:ns2="app2"> <ns2:complexType Name="Comp2"> <ns2:EntityType Name="a2"/> <ns2:EntityType Name="b2"/> </ns2:complexType> </ns2:Schema> </app2_selected_by_namespace_name> </apps> In both cases the names are not hardcoded but given by parameters. I guess that one of the versions will suit your needs. You will find the XPath expression in the select attributes of the copy-of tags.