I want get Order Lines for each Order and bring them to an EMail Body as Table like
Value 1 | Value 2 | Value 3
12345 ABC X1_
XML Code:
<?xml version="1.0" encoding="utf-8"?><UniversalInterchange xmlns= "http://www.designworker/namespace" version="1.1">
<Header> </Header>
<Body>
<UniversalShipment xmlns="http://www.designworker/namespace" version="1.1">
<Shipment>
<DataContext>
<DataTargetCollection>
<DataTarget>
<Type>SMTPTYPE</Type>
</DataTarget>
</DataTargetCollection>
</DataContext>
<Order>
<OrderNumber>99348234234</OrderNumber>
<OrderLineCollection>
<OrderLine>
<LineNumber>1</LineNumber>
<OrderedQty>455.000</OrderedQty>
<OrderedQtyUnit>
<Code>MORE</Code>
</OrderedQtyUnit>
<Product>
<Code>999LAM01</Code>
<Description>New Design Work</Description>
</Product>
<QuantityMet>1.000</QuantityMet>
<ShortfallQuantity>0</ShortfallQuantity>
</OrderLine>
<OrderLine>
<LineNumber>2</LineNumber>
<OrderedQty>655.000</OrderedQty>
<OrderedQtyUnit>
<Code>SOME</Code>
</OrderedQtyUnit>
<Product>
<Code>999LAM02</Code>
<Description>OLD Design Work </Description>
</Product>
<QuantityMet>3.000</QuantityMet>
<ShortfallQuantity>45</ShortfallQuantity>
</OrderLine>
</OrderLineCollection>
</Order>
</Shipment>
</UniversalShipment>
</Body>
</UniversalInterchange>
I have tried to solve this with this code:
var xDoc = XDocument.Parse(xmlValue);
XNamespace nsp = ns;
try
{
var value = xDoc
.Element(nsp + "UniversalInterchange")
.Element(nsp + "Body")
.Element(nsp + "UniversalShipment")
.Element(nsp + "Order")
.Element(nsp + "OrderLine")
.Element(nsp + "LineNumber")
.Value;
return value;
But when I have more than one Line in the Order it won't work.
How can I solve this on a better way ?
Looks like the navigation path is missing a few .Element()-calls.
var orderLines = xDoc
.Element(nsp + "UniversalInterchange")
.Element(nsp + "Body")
.Element(nsp + "UniversalShipment")
.Element(nsp + "Shipment")
.Element(nsp + "Order")
.Element(nsp + "OrderLineCollection")
.Elements(nsp + "OrderLine");
// 1, 2
var lineNumbers = orderLines.Select(x => x.Element(nsp + "LineNumber").Value);
Whenever an element isn't found, null is returned from .Element(). You should also use .Elements() instead of .Element() if you expect multiple entries.
Related
I have a Translation Memory which is essentially an XML file based on Translation Memory eXchange format specifications and I am trying to find a specific translation unit for editing. This is an example of the structure:
<?xml version="1.0" encoding="utf-8"?>
<tmx version="1.4">
<header creationtool="xxx" .... />
<body>
<tu tuid="1">
<tuv xml:lang="en-US">
<seg>sample source</seg>
</tuv>
<tuv xml:lang="de-DE">
<seg>sample translation</seg>
</tuv>
</tu>
<tu tuid="2">
<tuv xml:lang="en-US">
<seg>Address</seg>
</tuv>
<tuv xml:lang="de-DE">
<seg>Adresse</seg>
</tuv>
</tu>
.....
</body>
</tmx>
What I want is to be able to find all the translation units (tu) that have a specific source translation and a specific target translation. So for example I want to find all translation units where the xml language attribute value is "en-US" and the seg element value is "sample source" and the xml language attribute value is "de-DE" and its seg element value is "sample translation". I want to find
<tu tuid="18">
<tuv xml:lang="en-AU">
<seg>sample source</seg>
</tuv>
<tuv xml:lang="de-DE">
<seg>sample translation</seg>
</tuv>
</tu>
It is possible as well there is more than one translation unit (tu) that fits the criteria - that is there is possibly duplicates in the translation memory.
I have tried to get a collection I could iterate through e.g.
XElement root = XElement.Load(#"sample.tmx");
IEnumerable<XElement> translationUnits =
from el in root.Elements("tu")
where
(from tuv in el.Elements("tuv")
where
(string)tuv.Attribute(XNamespace.Xml + "lang") == "en-US" &&
(string)tuv.Element("seg") == "sample source"
select tuv)
.Any()
select el;
foreach (XElement el in translationUnits)
Console.WriteLine((string)el.Attribute("tuid"));
However I am obviously doing something wrong however I think I am on the right track. Once I find the collection I then want to update the target translation.
The way I eventually solved this for future reference is using XmlDocument
XmlDocument document = new XmlDocument();
document.Load(this.fileName);
string nodeSelect = "/tmx/body/tu/tuv[lang('" + this.sourceLanguage + "') and seg = '" + this.originalSourceText + "']";
XmlNodeList nodes = document.DocumentElement.SelectNodes(nodeSelect);
foreach (XmlNode node in nodes) {
XmlNode parent = node.ParentNode;
foreach (XmlNode translationNode in parent) {
string searchNode = "*[lang('" + this.targetLanguage + "') and //seg = '" + this.originalTranslationText + "']";
XmlNode test = translationNode.SelectSingleNode(searchNode);
if (test != null) {
if (test.InnerText.Equals(this.originalTranslationText, StringComparison.Ordinal)) {
test.InnerText = this.newTranslation;
}
}
}
}
The XML below is being returned from a web service. However, I cannot seem to get the value of or when using XElement.
<ResponseArray xmlns="urn:mdWebServiceAddress" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Version>2.0.62</Version>
<TransmissionReference></TransmissionReference>
<Results></Results>
<TotalRecords>1</TotalRecords>
<Record>
<RecordID>1</RecordID>
<Results>AC01,AS01</Results>
<Address>
<Address1>22382 Avenida Empresa</Address1>
<Address2></Address2>
<Suite></Suite>
<PrivateMailBox></PrivateMailBox>
<City>
<Name>Rancho Santa Margarita</Name>
<Abbreviation>Rcho Sta Marg</Abbreviation>
</City>
<State>
<Name>California</Name>
<Abbreviation>CA</Abbreviation>
</State>
<Zip>92688</Zip>
<Plus4>2112</Plus4>
<AddressKey>92688211282</AddressKey>
</Address>
</Record>
</ResponseArray>
Below is the code I am using to collect the values. Is the namespace being set incorrectly? How do I access the values of these elements in the XML.
XElement xelement = XElement.Parse(xmlString);
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
IEnumerable<XElement> records = xelement.Elements();
foreach (var record in records)
{
Console.WriteLine(record.Element(ns + "RecordID").Value);
Console.WriteLine(record.Element(ns + "Address").Element(ns + "AddressKey").Value);
}
a) change namespace
b) use Descendants
XNamespace ns = "urn:mdWebServiceAddress";
IEnumerable<XElement> records = xelement.Descendants(ns + "Record");
foreach (var record in records)
{
Console.WriteLine(record.Element(ns + "RecordID").Value);
Console.WriteLine(record.Element(ns + "Address").Element(ns + "AddressKey").Value);
}
PS: Safe way to use xml namespaces can be
XNamespace ns = xelement.GetDefaultNamespace();
Is possible to get the start tag string of an XElement?
For example, if i have an xml element like this
<Product Id="101" Name="Product 1">
<Images>
// ..
</Images>
<Description>
// ..
</Description>
</Product>
i want to get only the start tag:
<Product Id="101" Name="Product 1">
I use this for validation feedback purposes.
use query like
XElement xele = XElement.Load("xmlfilename");
XNamespace _XNamespace = XNamespace.Get("namespace url");
IEnumerable<XElement> ProductAttribute = from ele in xele .Descendants(_XNamespace + "Product ")
where ele.Attribute("Id").Value =="101" && ele.Attribute("Name") == "Product 1"
select ele;
Hope it will work for you
I know this is a very basic question but I'm new to XML and while it seems simple, I can't find a simple answer anywhere. I have an XML document that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<root version="1">
<targets>
<target type="email">
<property name="to">b1q23#email.com</property>
</target>
<target type="fob"/>
</targets>
<observation uniqueID="00A60D" deviceID="308610ea23">
<field name="field1">test1</field>
<field name="field2">test2</field>
</observation>
and I'm trying to either select a subset of that xml, or remove nodes, to get it pared down to:
<observation uniqueID="00A60D" deviceID="308610ea23">
<field name="attachments">
<string>1910.jpg</string>
</field>
<field name="field1">test1</field>
<field name="field2">test2</field>
</observation>
So that I can deserialize it into an object. Any help is greatly appreciated.
You can use XPath:
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<root version=\"1\">" +
"<targets>" +
"<target type=\"email\">" +
"<property name=\"to\">b1q23#email.com</property>" +
"</target>" +
"<target type=\"fob\"/>" +
"</targets>" +
"<observation uniqueID=\"00A60D\" deviceID=\"308610ea23\">" +
"<field name=\"field1\">test1</field>" +
"<field name=\"field2\">test2</field>" +
"</observation>" +
"</root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlElement root = doc.DocumentElement;
var observationNode = root.SelectSingleNode("/root/observation");
var observationXml = observationNode.OuterXml;
Here is a XML to LINQ Version:
dynamic root= XElement.Load(dataStream).Descendants("root")
.Select(element => element.Value).ToArray();
This will give all the root element from the document.And you can access root
XElement root = XElement.Parse("<root version ..." // etc. to parse a string.
// Use XElement.Load to load a file.
var observations = root.Elements("observation");
It assumes one root (by definition) and possibly multiple observation elements.
I am attempting to write a LINQ query to pull `ows_Alert="This is the text for an alert" into a list. there may be more than 1 "ows_Alert" so what I'm trying to do is retrieve a list of alerts, and place them as items of a split button drop-down menu.
I tried, attributes, and I tried elements, but htey are neither? How do I retrieve the ows_Alert value?
My code is as follows:
pAlerts= xDocument.Elements().ToList();
pAlerts.ForEach(item => tsSplitBtnAlerts.DropDownItems
.Add(item.Attribute("ows_Alert").ToString()));
The XML File
<?xml version="1.0" encoding="utf-8" ?>
<listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<rs:data ItemCount="1">
<z:row ows_ContentTypeId="0x0100D2769100E1771B4A94C86F01916A3C4F"
ows_Title="Alert Test"
ows_Alert="This is the text for an alert"
ows_ID="1" ows_ContentType="Item"
ows_Modified="2013-08-02 11:19:07" ows_Created="2013-08-02 11:19:07" ows_Author="1;#REDACTED" ows_Editor="1;#REDACTED"
ows_owshiddenversion="1" ows_WorkflowVersion="1" ows__UIVersion="512" ows__UIVersionString="1.0"
ows_Attachments="0" ows__ModerationStatus="0" ows_LinkTitleNoMenu="Alert Test" ows_LinkTitle="Alert Test"
ows_LinkTitle2="Alert Test" ows_SelectTitle="1" ows_Order="100.000000000000" ows_GUID="{77BD9162-461F-4A97-89E3-033E387E76A9}"
ows_FileRef="1;#Lists/PortalToolbarAlerts/1_.000" ows_FileDirRef="1;#Lists/PortalToolbarAlerts"
ows_Last_x0020_Modified="1;#2013-08-02 11:19:07" ows_Created_x0020_Date="1;#2013-08-02 11:19:07" ows_FSObjType="1;#0"
ows_SortBehavior="1;#0" ows_PermMask="0xb008431061" ows_FileLeafRef="1;#1_.000" ows_UniqueId="1;#{3E3EA8F8-16B2-4DD0-81B1-BAA9592302E9}"
ows_ProgId="1;#" ows_ScopeId="1;#{4310D927-E486-4B8C-8034-52937AC5A6D8}" ows__EditMenuTableStart="1_.000" ows__EditMenuTableStart2="1"
ows__EditMenuTableEnd="1" ows_LinkFilenameNoMenu="1_.000" ows_LinkFilename="1_.000" ows_LinkFilename2="1_.000"
ows_ServerUrl="/Lists/PortalToolbarAlerts/1_.000" ows_EncodedAbsUrl="http://REDACTEDSITE/1_.000"
ows_BaseName="1_" ows_MetaInfo="1;#" ows__Level="1" ows__IsCurrentVersion="1" ows_ItemChildCount="1;#0" ows_FolderChildCount="1;#0" />
</rs:data>
</listitems>
XNamespace z = "#RowsetSchema";
var alerts = xDocument.Descendants(z + "row")
.Select(row => (string)row.Attribute("ows_Alert"))
.ToList();
var ns = XNamespace.Get("#RowsetSchema");
var alerts = xml
.Descendants(ns + "row")
.Select(row => row.Attribute("ows_Alert").Value);
You have to include the namespaces when traversing the document. I tried this when using your xml in "test.xml" and it worked.
XDocument document = XDocument.Load(Server.MapPath("~/test.xml"), LoadOptions.None);
XNamespace ns = "urn:schemas-microsoft-com:rowset";
XNamespace z = "#RowsetSchema";
IEnumerable<XElement> datas = document.Root.Elements(ns + "data");
foreach (XElement data in datas)
{
IEnumerable<XElement> rows = data.Elements(z + "row");
string alerts = "";
foreach (XElement row in rows)
{
alerts += row.Attribute("ows_Alert").Value + "<br />";
}
Test.Text = alerts;
}