I have records in XML file like below. I need to search for <keyword>SEARCH</keyword> and if present
then I need to take the entire record and write to another file.(starting from <record> to </record>)
Below is my awk code which is inside loop. $1 holds line by line value of each record.
if(index($1,"SEARCH")>0)
{
print $1>> "output.txt"
}
This logic has two problems,
It is writing to output.txt file, only <keyword>SEARCH</keyword> element and not the whole record(starting from <record> to </record>)
SEARCH can also be present in <detail> tag. This code will even write that tag to output.txt
XML File:
<record category="xyz">
<person ssn="" e-i="E">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<names>
<first_name/>
<last_name></last_name>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>SEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is present in abc for xyz reason</detail>
</external_sources>
</details>
</record>
<record category="abc">
<person ssn="" e-i="F">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<names>
<first_name/>
<last_name></last_name>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>DONTSEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is not present in abc for xyz reason</detail>
</external_sources>
</details>
</record>
Use GNU awk for multi-char RS:
$ awk -v RS='</record>\n' '{ORS=RT} /<keyword>SEARCH<\/keyword>/' file
<record category="xyz">
<person ssn="" e-i="E">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<names>
<first_name/>
<last_name></last_name>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>SEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is present in abc for xyz reason</detail>
</external_sources>
</details>
</record>
If you need to search for any of multiple keywords then simply list them as such:
$ awk -v RS='</record>\n' '{ORS=RT} /<keyword>(SEARCH1|SEARCH2|SEARCH3)<\/keyword>/' file
$ cat x.awk
/<record / { i=1 }
i { a[i++]=$0 }
/<\/record>/ {
if (found) {
for (i=1; i<=length(a); ++i) print a[i] > "output.txt"
}
i=0;
found=0
}
/<keyword>SEARCH<\/keyword>/ { found=1 }
$ awk -f x.awk x.xml
$ cat output.txt
<record category="xyz">
<person ssn="" e-i="E">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<names>
<first_name/>
<last_name></last_name>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>SEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is present in abc for xyz reason</detail>
</external_sources>
</details>
</record>
You seem to have cross posted this question from Unix & Linux - I give the same answer here as I did there:
I'm going to assume that what you've posted is a sample, because it isn't valid XML. If this assumption isn't valid, my answer doesn't hold... but if that is the case, you really need to hit the person who gave you the XML with a rolled up copy of the XML spec, and demand they 'fix it'.
But really - awk and regular expressions are not the right tool for the job. An XML parser is. And with a parser, it's absurdly simple to do what you want:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
#parse your file - this will error if it's invalid.
my $twig = XML::Twig -> new -> parsefile ( 'your_xml' );
#set output format. Optional.
$twig -> set_pretty_print('indented_a');
#iterate all the 'record' nodes off the root.
foreach my $record ( $twig -> get_xpath ( './record' ) ) {
#if - beneath this record - we have a node anywhere (that's what // means)
#with a tag of 'keyword' and content of 'SEARCH'
#print the whole record.
if ( $record -> get_xpath ( './/keyword[string()="SEARCH"]' ) ) {
$record -> print;
}
}
xpath is quite a lot like regular expressions - in some ways - but it's more like a directory path. That means it's context aware, and can handle XML structures.
In the above: ./ means 'below current node' so:
$twig -> get_xpath ( './record' )
Means any 'top level' <record> tags.
But .// means "at any level, below current node" so it'll do it recursively.
$twig -> get_xpath ( './/search' )
Would get any <search> nodes at any level.
And the square brackets denote a condition - that's either a function (e.g. text() to get the text of the node) or you can use an attribute. e.g. //category[#name] would find any category with a name attribute, and //category[#name="xyz"] would filter those further.
XML used for testing:
<XML>
<record category="xyz">
<person ssn="" e-i="E">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<details>
<names>
<first_name/>
<last_name></last_name>
</names>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>SEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is present in abc for xyz reason</detail>
</external_sources>
</details>
</person>
</record>
<record category="abc">
<person ssn="" e-i="F">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<details>
<names>
<first_name/>
<last_name></last_name>
</names>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>DONTSEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is not present in abc for xyz reason</detail>
</external_sources>
</details>
</person>
</record>
</XML>
Output:
<record category="xyz">
<person
e-i="E"
ssn="">
<title xsi:nil="true" />
<position xsi:nil="true" />
<details>
<names>
<first_name/>
<last_name></last_name>
</names>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true" />
<keyword>SEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is present in abc for xyz reason</detail>
</external_sources>
</details>
</person>
</record>
Note - the above just prints the record to STDOUT. That's actually... in my opinion, not such a great idea. Not least because - it doesn't print the XML structure, and so it isn't actually 'valid' XML if you've more than one record (there's no "root" node).
So I would instead - to accomplish exactly what you're asking:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig -> new -> parsefile ('your_file.xml');
$twig -> set_pretty_print('indented_a');
foreach my $record ( $twig -> get_xpath ( './record' ) ) {
if ( not $record -> findnodes ( './/keyword[string()="SEARCH"]' ) ) {
$record -> delete;
}
}
open ( my $output, '>', "output.txt" ) or die $!;
print {$output} $twig -> sprint;
close ( $output );
This instead - inverts the logic, and deletes (from the parsed data structure in memory) the records you don't want, and prints the whole new structure (including XML headers) to a new file called "output.txt".
Related
I have XML files that I need to validate against XSDs that are nested inside a <wsdl:types></wsdl:types> in a WSDL file retrieved from a web service.
Inside the <wsdl:types></wsdl:types> there are several <xs:schema>s. I am using the ruby gem nokogiri to load the XML files and validate them against said XSDs, however, I am getting following error when I run the program:
Element '{http://schemas.xmlsoap.org/soap/envelope/}Envelope': No
matching global declaration available for the validation root.
So far I have extracted out the <xs:schema>s (all 4 of them) and copied them into a schema.xsd file.
Code:
require 'rubygems'
require 'nokogiri'
def validate(document_path, schema_path)
schema = Nokogiri::XML::Schema(File.read(schema_path))
document = Nokogiri::XML(File.read(document_path))
schema.validate(document)
end
validate('data.xml', 'schema.xsd').each do |error|
puts error.message
end
So basically my schema.xsd has multiple <xs:schema>s in there, which I do not think in and of itself is a problem because nokogiri didn't throw errors when I instantiated the schema object.
schema.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/">
<xs:element name="anyType" nillable="true" type="xs:anyType"/>
<xs:element name="anyURI" nillable="true" type="xs:anyURI"/>
<!-- data in here -->
</xs:schema>
<!-- three more xs:schema tags removed for brevity -->
data.xml
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header />
<env:Body>
<CreatePerson xmlns="https://person.example.com/">
<oMessageType xmlns:epa="http://schemas.datacontract.org/2004/07/whatever" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:array="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<person:bodyField>
<!-- data in here -->
</person:bodyField>
<!-- more data in here -->
</oMessageType>
</CreatePerson>
</env:Body>
</env:Envelope>
Yes, WSDL not the XSD scheam so you need to extract the schema partial manually or automatic by programming.
Here is the sample code, you need to refactor it and using in your codes.
str = <<EOF
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.examples.com/wsdl/HelloService.wsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloService" targetNamespace="http://www.examples.com/wsdl/HelloService.wsdl">
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/">
<element name="anyType" nillable="true" type="anyType"/>
<element name="anyURI" nillable="true" type="anyURI"/>
<!-- data in here -->
</schema>
</types>
<message name="SayHelloRequest">
<part name="firstName" type="xsd:string"/>
</message>
<message name="SayHelloResponse">
<part name="greeting" type="xsd:string"/>
</message>
<portType name="Hello_PortType">
<operation name="sayHello">
<input message="tns:SayHelloRequest"/>
<output message="tns:SayHelloResponse"/>
</operation>
</portType>
<binding name="Hello_Binding" type="tns:Hello_PortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="sayHello">
<soap:operation soapAction="sayHello"/>
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice"/>
</input>
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice"/>
</output>
</operation>
</binding>
<service name="Hello_Service">
<documentation>WSDL File for HelloService</documentation>
<port name="Hello_Port" binding="tns:Hello_Binding">
<soap:address location="http://www.examples.com/SayHello/"/>
</port>
</service>
</definitions>
EOF
require 'rubygems'
require 'nokogiri'
doc = Nokogiri::XML(str)
doc.root.children.each do |child|
if child.node_name == 'types'
types = child
# p types.inner_html
xsd_doc = Nokogiri::XML(types.inner_html)
# p xsd_doc.root
xsd = Nokogiri::XML::Schema.from_document xsd_doc.root
end
end
I am using an XQUERY FLWOR expression into an .xml file:
for $dynosaur in doc("document.xml")//species
let $dynosaurName := $dynosaur/text() // keeping the dynosaurName as a variable
return $dynosaur
The above return results like:
<species age="84">Velociraptor</species>
I need to format the result to be like:
<!ELEMENT dynosaur (Velociraptor) +>
so i am trying using the below but not working...
return <!ELEMENT dynosaur ({$dynosaurName}) +> //here i want that format but it return error
And the xml file:
<?xml version="1.0"?>
<dinosauria>
<group>
<name>saurishia</name>
<subgroups>
<group>
<name>theropoda</name>
<subgroups>
<group>
<name>carnosaurs</name>
<speciesList>
<species age="74">Dyptosaurus</species>
<species age="170">Megalosaurus</species>
<species age="67">Tyrannosaurus</species>
</speciesList>
</group>
<group>
<name>coelurosauria</name>
<speciesList>
<species age="84">Velociraptor</species>
<species age="110">Deinonychus</species>
<species age="228">Eoraptor</species>
</speciesList>
</group>
</subgroups>
</group>
<group>
<name>sauropodomorpha</name>
<subgroups>
<group>
<name>sauropods</name>
<speciesList>
<species age="155">Brachiosaurus</species>
<species age="155">Camarasaurus</species>
</speciesList>
</group>
</subgroups>
</group>
</subgroups>
</group>
<group>
<name>ornithishia</name>
<subgroups></subgroups>
</group>
</dinosauria>
Finally:
I can't find any way to return that type of result . I have checked a lot of links considering and this book : http://www.datypic.com/books/xquery/chapter09.html
Could you try outputting text?
return concat("<!ELEMENT dynosaur (",$dynosaurName, ") +>")
Im am trying to get the xml tag to be a part of the file name but im not getting any value. Am I doing something wrong? Im getting an error or a null value when I change the transformer
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:email="http://www.mulesoft.org/schema/mule/email" xmlns:pop3="http://www.mulesoft.org/schema/mule/pop3" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/pop3 http://www.mulesoft.org/schema/mule/pop3/current/mule-pop3.xsd
http://www.mulesoft.org/schema/mule/email http://www.mulesoft.org/schema/mule/email/current/mule-email.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd">
<flow name="email_notificationFlow">
<file:inbound-endpoint path="C:\Users\pd00h\Desktop\Knauf\testxML" responseTimeout="10000" doc:name="File"/>
<file:file-to-byte-array-transformer doc:name="File to Byte Array"/>
<set-variable variableName="order" value="#[xpath3('//ns0:Payload/WhsDockets/WhsDocket/Reference')]" doc:name="Variable"/>
<logger message="#[flowVars.order]" level="INFO" doc:name="Logger"/>
<file:outbound-endpoint path="C:\Users\pd00h\Desktop\Knauf" outputPattern="Knauf-#[message.id].xml" responseTimeout="10000" doc:name="File"/>
</flow>
</mule>
Sample Input File
<?xml version="1.0" encoding="utf-8"?><XmlInterchange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1" xmlns="http://www.edi.com.au/EnterpriseService/">
<InterchangeInfo>
<Date>2016-02-19T09:31:34.969+09:00</Date>
<XmlType>LightWeight</XmlType>
<Source>
<EnterpriseCode>AWH</EnterpriseCode>
<CompanyCode>ADL</CompanyCode>
<OriginServer>ADL</OriginServer>
</Source>
<Target />
<EDIOrganisation EDICode="AWHLOG_AU" OwnerCode="AWHLOG_AU">
<OrganisationDetails>
<Name>AWH LOGISTICS</Name>
<Location Country="Australia" City="Adelaide">AUADL</Location>
<Addresses>
<Address AddressType="MAIN">
<AddressLine1>Gillman Wool Complex</AddressLine1>
<AddressLine2>GRAND TRUNKWAY,</AddressLine2>
<AddressCode>Gillman Wool Complex</AddressCode>
<CityOrSuburb>GILLMAN</CityOrSuburb>
<StateOrProvince>SA</StateOrProvince>
<PostCode>5013</PostCode>
<TelephoneNumbers>
<TelephoneNumber NumberType="Business">+618 8240 8400</TelephoneNumber>
<TelephoneNumber NumberType="Fax">+618 8240 0080</TelephoneNumber>
</TelephoneNumbers>
<Email>containers#awh.com.au</Email>
<Language>ENG</Language>
<Location>AUADL</Location>
<Sequence>1</Sequence>
<AddressCapabilities>
<AddressCapability AddressType="MAIN" />
<AddressCapability IsMainAddress="true" AddressType="OFC" />
<AddressCapability IsMainAddress="true" AddressType="PAD" />
</AddressCapabilities>
</Address>
</Addresses>
</OrganisationDetails>
</EDIOrganisation>
</InterchangeInfo>
<Payload>
<WhsDockets>
<WhsDocket>
<Identifier>
<Client EDICode="KNAINSBNE" OwnerCode="KNAINSBNE">
<OrganisationDetails>
<Name>Knauf Insulation Pty Ltd</Name>
<Location Country="Australia" City="Brisbane">AUBNE</Location>
<Addresses>
<Address AddressType="MAIN">
<AddressLine1>2/44 BorthwickAve</AddressLine1>
<AddressCode>2/44 BorthwickAve</AddressCode>
<CityOrSuburb>MURARRIE</CityOrSuburb>
<StateOrProvince>QLD</StateOrProvince>
<PostCode>4172</PostCode>
<TelephoneNumbers>
<TelephoneNumber NumberType="Business">+61 (7) 3393-7300</TelephoneNumber>
<TelephoneNumber NumberType="Mobile">+61 (438) 488-000</TelephoneNumber>
<TelephoneNumber NumberType="Fax">+61 (7) 3343-1898</TelephoneNumber>
</TelephoneNumbers>
<Email>orders.au#knaufinsulation.com</Email>
<Language>ENG</Language>
<Location>AUBNE</Location>
<Sequence>1</Sequence>
<AddressCapabilities>
<AddressCapability AddressType="MAIN" />
<AddressCapability IsMainAddress="true" AddressType="OFC" />
</AddressCapabilities>
</Address>
</Addresses>
</OrganisationDetails>
</Client>
<Reference>2363867</Reference>
<DocketType>WOH</DocketType>
<ActionType>CON</ActionType>
</Identifier>
<DocketDetail>
<WarehouseCode>ROC</WarehouseCode>
<CustomerReference>3330826</CustomerReference>
<Units>80</Units>
<Packages>0</Packages>
<Pallets>0</Pallets>
<Weight DimensionType="KG">673</Weight>
<Cubic DimensionType="M3">7.624</Cubic>
<TransportInsurance>0.0000</TransportInsurance>
<ShipperCODAmount>0.0000</ShipperCODAmount>
<CustomerOrderDetail>
<OrderType>ORD</OrderType>
<DateRequired>2015-08-25T00:00:00</DateRequired>
<Consignee AddressType="CEA">
<AddressLine1>71-83 Kenny Street</AddressLine1>
<CityOrSuburb>PORTSMITH</CityOrSuburb>
<StateOrProvince>QLD</StateOrProvince>
<PostCode>4870</PostCode>
<CompanyName>Bunnings Cairns Central Warehouse</CompanyName>
<CountryCode>AU</CountryCode>
<ContactName>The Import Manager</ContactName>
</Consignee>
</CustomerOrderDetail>
<CustomAttributes />
</DocketDetail>
<DocketLines>
<DocketLine>
<Product>E2271</Product>
<Description>R 3 0 145mm x 580mm x 1160mm</Description>
<QuantityFromClientOrder>4</QuantityFromClientOrder>
<QuantityActuallyOrdered>4</QuantityActuallyOrdered>
<ProductUQ>MST</ProductUQ>
<LineAttributes />
<LineNumber>1</LineNumber>
<Confirmation>
<Lines>
<Line>
<Quantity>16</Quantity>
<QuantityUQ>PAC</QuantityUQ>
</Line>
</Lines>
<Quantity>16</Quantity>
</Confirmation>
</DocketLine>
<DocketLine>
<Product>E4386</Product>
<Description>R 2 0 90mm x 580mm x 19000mm</Description>
<QuantityFromClientOrder>4</QuantityFromClientOrder>
<QuantityActuallyOrdered>4</QuantityActuallyOrdered>
<ProductUQ>MST</ProductUQ>
<LineAttributes />
<LineNumber>2</LineNumber>
<Confirmation>
<Lines>
<Line>
<Quantity>32</Quantity>
<QuantityUQ>PAC</QuantityUQ>
</Line>
</Lines>
<Quantity>32</Quantity>
</Confirmation>
</DocketLine>
<DocketLine>
<Product>450521</Product>
<Description>XPS300 30 x 600 x 1200 B1 / On / SE</Description>
<QuantityFromClientOrder>20</QuantityFromClientOrder>
<QuantityActuallyOrdered>20</QuantityActuallyOrdered>
<ProductUQ>PC</ProductUQ>
<LineAttributes />
<LineNumber>3</LineNumber>
<Confirmation>
<Lines>
<Line>
<Quantity>20</Quantity>
<QuantityUQ>PC</QuantityUQ>
</Line>
</Lines>
<Quantity>20</Quantity>
</Confirmation>
</DocketLine>
<DocketLine>
<Product>450523</Product>
<Description>XPS300 50 x 600 x 1200 B1 / On / SE</Description>
<QuantityFromClientOrder>12</QuantityFromClientOrder>
<QuantityActuallyOrdered>12</QuantityActuallyOrdered>
<ProductUQ>PC</ProductUQ>
<LineAttributes />
<LineNumber>4</LineNumber>
<Confirmation>
<Lines>
<Line>
<Quantity>12</Quantity>
<QuantityUQ>PC</QuantityUQ>
</Line>
</Lines>
<Quantity>12</Quantity>
</Confirmation>
</DocketLine>
</DocketLines>
</WhsDocket>
</WhsDockets>
</Payload>
Can you use this to complex XML structures?
Add namespace-manager
replace file:file-to-byte-array-transformer
with byte-array-to-string-transformer
fix xpath usage
updated code:
<mule xmlns:file="http://www.mulesoft.org/schema/mule/file"
xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:email="http://www.mulesoft.org/schema/mule/email"
xmlns:pop3="http://www.mulesoft.org/schema/mule/pop3" xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/pop3 http://www.mulesoft.org/schema/mule/pop3/current/mule-pop3.xsd
http://www.mulesoft.org/schema/mule/email http://www.mulesoft.org/schema/mule/email/current/mule-email.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd">
<mulexml:namespace-manager
includeConfigNamespaces="true">
<mulexml:namespace prefix="ns0"
uri="http://www.example.com/something.xsd" />
</mulexml:namespace-manager>
<flow name="email_notificationFlow">
<file:inbound-endpoint path="C:\Users\pd00h\Desktop\Knauf\testxML"
responseTimeout="10000" doc:name="File" />
<byte-array-to-string-transformer
doc:name="Byte Array to String" />
<set-variable variableName="order"
value="#[xpath3('//ns0:WhsDockets/ns0:WhsDocket/ns0:Reference')]"
doc:name="Variable" />
<logger message="#[flowVars.order]" level="INFO" doc:name="Logger" />
<file:outbound-endpoint path="C:\Users\pd00h\Desktop\Knauf"
outputPattern="Knauf-#[message.id].xml" responseTimeout="10000"
doc:name="File" />
</flow>
</mule>
Sample xml file:
<?xml version='1.0' encoding='UTF-8'?>
<ns0:WhsDockets xmlns:ns0="http://www.example.com/something.xsd">
<ns0:WhsDocket>
<ns0:Reference>GotIt!</ns0:Reference>
</ns0:WhsDocket>
</ns0:WhsDockets>
Cheers
<document>
<element>
<attribut a:name="my-name">My Name</attribut>
<attribut a:parent="parent1">Parent 1</attribut>
</element>
</document>
In this XML document, how to select the node which has the attribut a:name ?
$xmlTest = <<<XML
<?xml version="1.0" encoding="UTF-8" ?>
<document xmlns:a="http://example.org/a">
<element>
<attribut a:name="my-name">My Name</attribut>
<attribut a:parent="parent1">Parent 1</attribut>
</element>
</document>
XML;
$xml = new SimpleXMLElement($xmlTest);
echo current($xml->xpath('//element/attribut[#a:name]'));
I have complex soap XML like below.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<MessageHeader>
<From>
<Type>string</Type>
</d3p1:From>
<d3p1:To>
<Role>string</Role>
</d3p1:To>
</MessageHeader>
<Security xmlns="http://schemas.xmlsoap.org/ws/2002/12/sxvt">
<StrongToken>string</StrongToken>
</Security>
</soap:Header>
<soap:Body>
<FunctionResponse xmlns="http://www.yyy.com/webservices">
<FunctionRS TimeStamp="dateTime">
<Message>string<Message>
<Success>
<SuccessMessage>string</SuccessMessage>
</Success>
<Warnings>
<Warning Type="string" Text="string" />
<Warning Type="string" Text="string" />
</Warnings>
<Errors>
<Error Type="string" Text="string" />
<Error Type="string" Text="string" />
</Errors>
<Items>
<Item SequenceNo="Int" ">
<SamplePrice>
<Prices>
<Price>
<ToatlPrice>
<ItemNo>Int </ItemNo>
<ItemPrice>Int </ItemPrice>
</ToatlPrice>
</Price>
</Prices>
</SamplePrice >
</Item>
<Item SequenceNo="Int" ">
<SamplePrice>
<Prices>
<Price>
<ToatlPrice>
<ItemNo>Int </ItemNo>
<ItemPrice>Int </ItemPrice>
</ToatlPrice>
</Price>
</Prices>
</SamplePrice >
</Item>
</Items>
<Info>
<CurrencyCode>
<string>string</string>
<string>string</string>
</CurrencyCode>
</Infor>
</FunctionRS>
</FunctionResponse>
</soap:Body>
</soap:Envelope>
here i want the results of FunctionRS tag. I have created the class for the FunctionRS tag.
I have created FunctionRS class.
var result = resultNewDataSet.Descendants("FunctionRS").Select(t => new FunctionRS
{
Message = t.Descendants("Message").First().Value,
//Success = t.Descendants("Success").First().Value
});
using the above code i am able to get Message tag, but i am not able get the array lists (like Success, warnings,Items,etc) and class (like Info).
How can i Serialize the above xml using LINQ to XML.
Thanks in advance.
Elements you are looking for are in http://www.yyy.com/webservices namespace however in your query you are not using namespaces. I am not sure how FunctionRS or Message could be found as you are looking for them in the empty namespace. Try the following:
var resultNewDataSet = XDocument.Parse(
#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:d3p1=""unknownnamespace"">
<soap:Header>
<MessageHeader>
<d3p1:From>
<Type>string</Type>
</d3p1:From>
<d3p1:To>
<Role>string</Role>
</d3p1:To>
</MessageHeader>
<Security xmlns=""http://schemas.xmlsoap.org/ws/2002/12/sxvt"">
<StrongToken>string</StrongToken>
</Security>
</soap:Header>
<soap:Body>
<FunctionResponse xmlns=""http://www.yyy.com/webservices"">
<FunctionRS TimeStamp=""dateTime"">
<Message>string</Message>
<Success>
<SuccessMessage>string</SuccessMessage>
</Success>
<Warnings>
<Warning Type=""string"" Text=""string"" />
<Warning Type=""string"" Text=""string"" />
</Warnings>
<Errors>
<Error Type=""string"" Text=""string"" />
<Error Type=""string"" Text=""string"" />
</Errors>
<Items>
<Item SequenceNo=""Int"">
<SamplePrice>
<Prices>
<Price>
<ToatlPrice>
<ItemNo>Int </ItemNo>
<ItemPrice>Int </ItemPrice>
</ToatlPrice>
</Price>
</Prices>
</SamplePrice >
</Item>
<Item SequenceNo=""Int"">
<SamplePrice>
<Prices>
<Price>
<ToatlPrice>
<ItemNo>Int </ItemNo>
<ItemPrice>Int </ItemPrice>
</ToatlPrice>
</Price>
</Prices>
</SamplePrice >
</Item>
</Items>
<Info>
<CurrencyCode>
<string>string</string>
<string>string</string>
</CurrencyCode>
</Info>
</FunctionRS>
</FunctionResponse>
</soap:Body>
</soap:Envelope>");
XNamespace webServicesNs = "http://www.yyy.com/webservices";
var result = resultNewDataSet
.Descendants(webServicesNs + "FunctionRS")
.Select(t => new
{
Message = (string)t.Descendants(webServicesNs + "Message").First(),
Success = (string)t.Descendants(webServicesNs + "Success").First(),
Warnings = t
.Element(webServicesNs + "Warnings")
.Elements(webServicesNs + "Warning")
.Select(w => new
{
#Type = (string)w.Attribute("Type"),
#Text = (string)w.Attribute("Text")
})
});
foreach (var r in result)
{
Console.WriteLine(r);
foreach (var w in r.Warnings)
{
Console.WriteLine(w);
}
}
(I included the Xml since the one you provided was broken and I had to fix it to make it possible to load to XDocument).
Here is the result I got:
{ Message = string, Success = string, Warnings = System.Linq.Enumerable+WhereSel
ectEnumerableIterator`2[System.Xml.Linq.XElement,<>f__AnonymousType0`2[System.St
ring,System.String]] }
{ Type = string, Text = string }
{ Type = string, Text = string }