XPath: Select element which has specific attribute with special character - xpath

<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]'));

Related

how to disable schema validation in JAX-RS or remove ns2 from response on client side?

3rd Party API had the following response created for my JAX-RS request:
<?xml version="1.0"?>
<name xmlns="http://www.example.com/name">
<first>John</first>
<middle>M</middle>
<last>Doe</last>
</name>
referring to this schema:
<?xml version="1.0"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:target="http://www.example.com/name"
targetNamespace="http://www.example.com/name" elementFormDefault="qualified">
<element name="name">
<complexType>
<sequence>
<element name="first" type="string"/>
<element name="middle" type="string"/>
<element name="last" type="string"/>
</sequence>
</complexType>
</element>
</schema>
However , they changed the server response to this by mistake:
<?xml version="1.0"?>
<ns2:name xmlns:ns2="http://www.example.com/name">
<first>John</first>
<middle>M</middle>
<last>Doe</last>
</ns2:name>
Now when I call the API using JAX-RS webclient, I have NOT null Response object , but the value inside it is all null as the child nodes of the XML response is not using namespace ns2.
How do I ignore namespace ns2? so the response object value will not be null.

Parsing XML file with nokogiri

I have the following xml file:
<?xml version='1.0' encoding='UTF-8'?>
<sparql xmlns='http://www.w3.org/2005/sparql-results#'>
<head>
<variable name='s'/>
</head>
<results>
<result>
<binding name='s'>
<uri>http://data.open.ac.uk/podcast/c9ddc42f6e1db95f59c83312d62da0ee</uri>
</binding>
</result>
<result>
<binding name='s'>
<uri>http://data.open.ac.uk/podcast/18873effb6c38ed83a7522ffb7c61c1b</uri>
</binding>
</result>
</results>
</sparql>
I want to get the uris from the document. I tried these commands:
doc = Nokogiri::XML(File.open("file.xml"))
doc.xpath("//uri")
but it returns nil.
However, if I modified the file to this:
<results>
<result>
<binding name='s'>
<uri>http://data.open.ac.uk/podcast/c9ddc42f6e1db95f59c83312d62da0ee</uri>
</binding>
</result>
<result>
<binding name='s'>
<uri>http://data.open.ac.uk/podcast/18873effb6c38ed83a7522ffb7c61c1b</uri>
</binding>
</result>
</results>
The above commands return the uris correctly.
You need to specify the namespace of the element you're trying to select. In the first document this is http://www.w3.org/2005/sparql-results#, inherited from the root-node. In the second document it works, because you're removed the namespace declaration by removing that root node.
The good news is because your namespace is defined in the root node Nokogiri will automatically register it for you, and you should be able to select the <uri> elements with
doc.xpath("//xmlns:uri")

Rabl: Multiple nodes with the same name

I have the following code for generating a xml from a rabl template:
obj = OpenStruct.new
obj.categories = [{node: ["Foo","Bar"]},{node: ["Test1","Test2"]}]
Rabl::Renderer.xml(obj, 'adapter_xml')
and this is the rabl template adapter_xml.rabl
object #obj => :root
attributes :categories
which generates this XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<categories>
<category>
<node>
<node>Foo</node>
<node>Bar</node>
</node>
</category>
<category>
<node>
<node>Test1</node>
<node>Test2</node>
</node>
</category>
</categories>
</root>
But what I want to achieve is the following format, without the extra <node> tags:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<categories>
<category>
<node>Foo</node>
<node>Bar</node>
</category>
<category>
<node>Test1</node>
<node>Test2</node>
</category>
</categories>
</root>
Is there any way to do this with rabl? Or do I have to modify the ruby code mentioned first?

How to get parent node?

//* [ local-name()='component' and namespace-uri()='urn:hl7-org:v3' ]
Using thispath, I can get a node like this:
<?xml version="1.0" encoding="utf-8"?>
<ClinicalDocument xmlns="urn:hl7-org:v3">
<component>
<structuredBody>
<component>
<section>
<code code="10164-2" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC"/>
<title>History of Present Illness</title>
<text>
</text>
</section>
</component>
<component> ...... </component>
<component> ...... </component>
</structuredBody>
</component>
</ClinicalDocument>
In order to get the node as below:
<component>
<section>
<code code="10164-2" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC"/>
<title>History of Present Illness</title>
<text>
</text>
</section>
</component>
I change the path to :
//* [ local-name()='component' and namespace-uri()='urn:hl7-org:v3' and position()=1]
But, how can I get the same result by using [code="10164-2"] as a qualification?
edit 2012-12-17
//:component[1]//:component[.//:section/:code[#code='10164-2']]
this xpath works well and I can get the node I want . What should I do If I use
//*[local-name()='component' and namespace-uri()='urn:hl7-org:v3'])[1]
to select the parent <component/>node then add [#code='10164-2'] to the predicate part to get the <component/>child node i want. (I would like not to use : in the path to avoid namespace issue)
Use:
((//*[local-name()='component'
and namespace-uri()='urn:hl7-org:v3']
)[1]
//*[local-name()='component'
and
namespace-uri()='urn:hl7-org:v3'
]
)[1]
XSLT - based verification:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select=
"((//*[local-name()='component'
and namespace-uri()='urn:hl7-org:v3']
)[1]
//*[local-name()='component'
and
namespace-uri()='urn:hl7-org:v3']
)[1]
"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<component xmlns="urn:hl7-org:v3">
<structuredBody>
<component>
<section>
<code code="10164-2" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC"/>
<title>History of Present Illness</title>
<text>
</text>
</section>
</component>
<component> ...... </component>
<component> ...... </component>
</structuredBody>
</component>
the XPath expression is evaluated and the results of this evaluation are copied to the output:
<component xmlns="urn:hl7-org:v3">
<section>
<code code="10164-2" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC"/>
<title>History of Present Illness</title>
<text/>
</section>
</component>
Just add and section/code/#code='10164-2' to your predicate:
//*:component[namespace-uri()='urn:hl7-org:v3' and section/code/#code='10164-2']
Note: You may have to remove namespace-uri()='urn:hl7-org:v3' if component isn't in that namespace. Your example in "in order to get the node as below:" does not have a namespace.
Also, I used *:component instead of local-name() since you tagged the question XPath 2.0.

Parsing complex soap XML in windows phone 7

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 }

Resources