XQuery - remove nodes based on its sub element being in the "ban" list - xquery

I am a total noob with XQuery, but before at start digging deep into it, i'd like to ask some experts advice about whether i am looking at the correct direction.
The problem:
A huge xml file which contains a whole lot of users and their access information (password access rights and so on) example below:
<user>
<name>JC1234</name>
<password>popstar</password>
<accesslevel>0</accesslevel>
</user>
<user>
<name>AHkl</name>
<password>Rudy10!</password>
<accesslevel>2</accesslevel>
</user>
i have a list of user names (csv file) that i need to remove from that huge xml files.
the result should be a new xml file wihtout those removed users....
is this feasable with XQuery?
any advice for a quick and dirty solution is welcomed!

There is no standard way of loading a CSV file in vanilla XQuery 1.0, although most implementations have an unparsed-text function or similar. If not the contents of the file can be passed in as a parameter.
The CSV file can be parsed using the tokenize function:
declare variable $names = tokenize(unparsed-text("banned.csv"), ",")
And the actual query is quite straightforward. Assuming your document is a a fragment containing just a list of <user /> nodes then the query is simply
doc("users.xml")/user[not(name=$names)]
If however the XML file contains a lot of other data then you may find XSLT's templating facilities more useful.

Related

How to resolve PCDATA invalid Char value 27 [9] error when parsing XML in R [duplicate]

Currently, I'm working on a feature that involves parsing XML that we receive from another product. I decided to run some tests against some actual customer data, and it looks like the other product is allowing input from users that should be considered invalid. Anyways, I still have to try and figure out a way to parse it. We're using javax.xml.parsers.DocumentBuilder and I'm getting an error on input that looks like the following.
<xml>
...
<description>Example:Description:<THIS-IS-PART-OF-DESCRIPTION></description>
...
</xml>
As you can tell, the description has what appears to be an invalid tag inside of it (<THIS-IS-PART-OF-DESCRIPTION>). Now, this description tag is known to be a leaf tag and shouldn't have any nested tags inside of it. Regardless, this is still an issue and yields an exception on DocumentBuilder.parse(...)
I know this is invalid XML, but it's predictably invalid. Any ideas on a way to parse such input?
That "XML" is worse than invalid – it's not well-formed; see Well Formed vs Valid XML.
An informal assessment of the predictability of the transgressions does not help. That textual data is not XML. No conformant XML tools or libraries can help you process it.
Options, most desirable first:
Have the provider fix the problem on their end. Demand well-formed XML. (Technically the phrase well-formed XML is redundant but may be useful for emphasis.)
Use a tolerant markup parser to cleanup the problem ahead of parsing as XML:
Standalone: xmlstarlet has robust recovering and repair capabilities credit: RomanPerekhrest
xmlstarlet fo -o -R -H -D bad.xml 2>/dev/null
Standalone and C/C++: HTML Tidy works with XML too. Taggle is a port of TagSoup to C++.
Python: Beautiful Soup is Python-based. See notes in the Differences between parsers section. See also answers to this question for more
suggestions for dealing with not-well-formed markup in Python,
including especially lxml's recover=True option.
See also this answer for how to use codecs.EncodedFile() to cleanup illegal characters.
Java: TagSoup and JSoup focus on HTML. FilterInputStream can be used for preprocessing cleanup.
.NET:
XmlReaderSettings.CheckCharacters can
be disabled to get past illegal XML character problems.
#jdweng notes that XmlReaderSettings.ConformanceLevel can be set to
ConformanceLevel.Fragment so that XmlReader can read XML Well-Formed Parsed Entities lacking a root element.
#jdweng also reports that XmlReader.ReadToFollowing() can sometimes
be used to work-around XML syntactical issues, but note
rule-breaking warning in #3 below.
Microsoft.Language.Xml.XMLParser is said to be “error-tolerant”.
Go: Set Decoder.Strict to false as shown in this example by #chuckx.
PHP: See DOMDocument::$recover and libxml_use_internal_errors(true). See nice example here.
Ruby: Nokogiri supports “Gentle Well-Formedness”.
R: See htmlTreeParse() for fault-tolerant markup parsing in R.
Perl: See XML::Liberal, a "super liberal XML parser that parses broken XML."
Process the data as text manually using a text editor or
programmatically using character/string functions. Doing this
programmatically can range from tricky to impossible as
what appears to be
predictable often is not -- rule breaking is rarely bound by rules.
For invalid character errors, use regex to remove/replace invalid characters:
PHP: preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $s);
Ruby: string.tr("^\u{0009}\u{000a}\u{000d}\u{0020}-\u{D7FF}\u{E000‌​}-\u{FFFD}", ' ')
JavaScript: inputStr.replace(/[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm, '')
For ampersands, use regex to replace matches with &: credit: blhsin, demo
&(?!(?:#\d+|#x[0-9a-f]+|\w+);)
Note that the above regular expressions won't take comments or CDATA
sections into account.
A standard XML parser will NEVER accept invalid XML, by design.
Your only option is to pre-process the input to remove the "predictably invalid" content, or wrap it in CDATA, prior to parsing it.
The accepted answer is good advice, and contains very useful links.
I'd like to add that this, and many other cases of not-wellformed and/or DTD-invalid XML can be repaired using SGML, the ISO-standardized superset of HTML and XML. In your case, what works is to declare the bogus THIS-IS-PART-OF-DESCRIPTION element as SGML empty element and then use eg. the osx program (part of the OpenSP/OpenJade SGML package) to convert it to XML. For example, if you supply the following to osx
<!DOCTYPE xml [
<!ELEMENT xml - - ANY>
<!ELEMENT description - - ANY>
<!ELEMENT THIS-IS-PART-OF-DESCRIPTION - - EMPTY>
]>
<xml>
<description>blah blah
<THIS-IS-PART-OF-DESCRIPTION>
</description>
</xml>
it will output well-formed XML for further processing with the XML tools of your choice.
Note, however, that your example snippet has another problem in that element names starting with the letters xml or XML or Xml etc. are reserved in XML, and won't be accepted by conforming XML parsers.
IMO these cases should be solved by using JSoup.
Below is a not-really answer for this specific case, but found this on the web (thanks to inuyasha82 on Coderwall). This code bit did inspire me for another similar problem while dealing with malformed XMLs, so I share it here.
Please do not edit what is below, as it is as it on the original website.
The XML format, requires to be valid a unique root element declared in the document.
So for example a valid xml is:
<root>
<element>...</element>
<element>...</element>
</root>
But if you have a document like:
<element>...</element>
<element>...</element>
<element>...</element>
<element>...</element>
This will be considered a malformed XML, so many xml parsers just throw an Exception complaining about no root element. Etc.
In this example there is a solution on how to solve that problem and succesfully parse the malformed xml above.
Basically what we will do is to add programmatically a root element.
So first of all you have to open the resource that contains your "malformed" xml (i. e. a file):
File file = new File(pathtofile);
Then open a FileInputStream:
FileInputStream fis = new FileInputStream(file);
If we try to parse this stream with any XML library at that point we will raise the malformed document Exception.
Now we create a list of InputStream objects with three lements:
A ByteIputStream element that contains the string: <root>
Our FileInputStream
A ByteInputStream with the string: </root>
So the code is:
List<InputStream> streams =
Arrays.asList(
new ByteArrayInputStream("<root>".getBytes()),
fis,
new ByteArrayInputStream("</root>".getBytes()));
Now using a SequenceInputStream, we create a container for the List created above:
InputStream cntr =
new SequenceInputStream(Collections.enumeration(str));
Now we can use any XML Parser library, on the cntr, and it will be parsed without any problem. (Checked with Stax library);

MuleSoft - Running Batch job using XML array

I am trying to run a Batch Job using XML array. My XML structure looks like below.
<file>
<data>
<deliveryOrder>
<deliveryMethod>TRUCK1</deliveryMethod>
</deliveryOrder>
<deliveryOrder>
<deliveryMethod>TRUCK21</deliveryMethod>
</deliveryOrder>
<deliveryOrder>
<deliveryMethod>TRUCK2</deliveryMethod>
</deliveryOrder>
</data>
</file>
At the moment my batch step only runs once with entire xml. My requirement is to run batch-step for each 'deliveryOrder'. One solution is to convert it to JSON, which works fine. However, I don't want to do that since target systems use xml interface.
Please advice if there is a way to run batch on XML items directly.
Thanks
Batch doesn't know about JSON or XML, it knows about consuming iterable inputs. JSON has the concept of arrays and probably that's the reason it works. XML has no concept of arrays. It has nested elements, that some implementations might treat as an array. Converting XML to JSON just for batch processing is very inefficient, as the payload will need to be parsed and transformed to the internal representation twice.
One alternative is to just use DataWeave to transform to a Java array of the elements to process:
%dw 2.0
output application/java
---
payload.file.data.*deliveryOrder
This returns an array of all deliverOrder elements under file.data.

Error: 1: PCDATA invalid Char value 8 when reading XML file [duplicate]

Currently, I'm working on a feature that involves parsing XML that we receive from another product. I decided to run some tests against some actual customer data, and it looks like the other product is allowing input from users that should be considered invalid. Anyways, I still have to try and figure out a way to parse it. We're using javax.xml.parsers.DocumentBuilder and I'm getting an error on input that looks like the following.
<xml>
...
<description>Example:Description:<THIS-IS-PART-OF-DESCRIPTION></description>
...
</xml>
As you can tell, the description has what appears to be an invalid tag inside of it (<THIS-IS-PART-OF-DESCRIPTION>). Now, this description tag is known to be a leaf tag and shouldn't have any nested tags inside of it. Regardless, this is still an issue and yields an exception on DocumentBuilder.parse(...)
I know this is invalid XML, but it's predictably invalid. Any ideas on a way to parse such input?
That "XML" is worse than invalid – it's not well-formed; see Well Formed vs Valid XML.
An informal assessment of the predictability of the transgressions does not help. That textual data is not XML. No conformant XML tools or libraries can help you process it.
Options, most desirable first:
Have the provider fix the problem on their end. Demand well-formed XML. (Technically the phrase well-formed XML is redundant but may be useful for emphasis.)
Use a tolerant markup parser to cleanup the problem ahead of parsing as XML:
Standalone: xmlstarlet has robust recovering and repair capabilities credit: RomanPerekhrest
xmlstarlet fo -o -R -H -D bad.xml 2>/dev/null
Standalone and C/C++: HTML Tidy works with XML too. Taggle is a port of TagSoup to C++.
Python: Beautiful Soup is Python-based. See notes in the Differences between parsers section. See also answers to this question for more
suggestions for dealing with not-well-formed markup in Python,
including especially lxml's recover=True option.
See also this answer for how to use codecs.EncodedFile() to cleanup illegal characters.
Java: TagSoup and JSoup focus on HTML. FilterInputStream can be used for preprocessing cleanup.
.NET:
XmlReaderSettings.CheckCharacters can
be disabled to get past illegal XML character problems.
#jdweng notes that XmlReaderSettings.ConformanceLevel can be set to
ConformanceLevel.Fragment so that XmlReader can read XML Well-Formed Parsed Entities lacking a root element.
#jdweng also reports that XmlReader.ReadToFollowing() can sometimes
be used to work-around XML syntactical issues, but note
rule-breaking warning in #3 below.
Microsoft.Language.Xml.XMLParser is said to be “error-tolerant”.
Go: Set Decoder.Strict to false as shown in this example by #chuckx.
PHP: See DOMDocument::$recover and libxml_use_internal_errors(true). See nice example here.
Ruby: Nokogiri supports “Gentle Well-Formedness”.
R: See htmlTreeParse() for fault-tolerant markup parsing in R.
Perl: See XML::Liberal, a "super liberal XML parser that parses broken XML."
Process the data as text manually using a text editor or
programmatically using character/string functions. Doing this
programmatically can range from tricky to impossible as
what appears to be
predictable often is not -- rule breaking is rarely bound by rules.
For invalid character errors, use regex to remove/replace invalid characters:
PHP: preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $s);
Ruby: string.tr("^\u{0009}\u{000a}\u{000d}\u{0020}-\u{D7FF}\u{E000‌​}-\u{FFFD}", ' ')
JavaScript: inputStr.replace(/[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm, '')
For ampersands, use regex to replace matches with &: credit: blhsin, demo
&(?!(?:#\d+|#x[0-9a-f]+|\w+);)
Note that the above regular expressions won't take comments or CDATA
sections into account.
A standard XML parser will NEVER accept invalid XML, by design.
Your only option is to pre-process the input to remove the "predictably invalid" content, or wrap it in CDATA, prior to parsing it.
The accepted answer is good advice, and contains very useful links.
I'd like to add that this, and many other cases of not-wellformed and/or DTD-invalid XML can be repaired using SGML, the ISO-standardized superset of HTML and XML. In your case, what works is to declare the bogus THIS-IS-PART-OF-DESCRIPTION element as SGML empty element and then use eg. the osx program (part of the OpenSP/OpenJade SGML package) to convert it to XML. For example, if you supply the following to osx
<!DOCTYPE xml [
<!ELEMENT xml - - ANY>
<!ELEMENT description - - ANY>
<!ELEMENT THIS-IS-PART-OF-DESCRIPTION - - EMPTY>
]>
<xml>
<description>blah blah
<THIS-IS-PART-OF-DESCRIPTION>
</description>
</xml>
it will output well-formed XML for further processing with the XML tools of your choice.
Note, however, that your example snippet has another problem in that element names starting with the letters xml or XML or Xml etc. are reserved in XML, and won't be accepted by conforming XML parsers.
IMO these cases should be solved by using JSoup.
Below is a not-really answer for this specific case, but found this on the web (thanks to inuyasha82 on Coderwall). This code bit did inspire me for another similar problem while dealing with malformed XMLs, so I share it here.
Please do not edit what is below, as it is as it on the original website.
The XML format, requires to be valid a unique root element declared in the document.
So for example a valid xml is:
<root>
<element>...</element>
<element>...</element>
</root>
But if you have a document like:
<element>...</element>
<element>...</element>
<element>...</element>
<element>...</element>
This will be considered a malformed XML, so many xml parsers just throw an Exception complaining about no root element. Etc.
In this example there is a solution on how to solve that problem and succesfully parse the malformed xml above.
Basically what we will do is to add programmatically a root element.
So first of all you have to open the resource that contains your "malformed" xml (i. e. a file):
File file = new File(pathtofile);
Then open a FileInputStream:
FileInputStream fis = new FileInputStream(file);
If we try to parse this stream with any XML library at that point we will raise the malformed document Exception.
Now we create a list of InputStream objects with three lements:
A ByteIputStream element that contains the string: <root>
Our FileInputStream
A ByteInputStream with the string: </root>
So the code is:
List<InputStream> streams =
Arrays.asList(
new ByteArrayInputStream("<root>".getBytes()),
fis,
new ByteArrayInputStream("</root>".getBytes()));
Now using a SequenceInputStream, we create a container for the List created above:
InputStream cntr =
new SequenceInputStream(Collections.enumeration(str));
Now we can use any XML Parser library, on the cntr, and it will be parsed without any problem. (Checked with Stax library);

Missing Root node in xml file in biztalk

I have researched a lot on internet, but still not able to get exact solution for my problem. The problem mentioned in below link is much similar to mine, but this will not work.
If record exists then map, if not map another - Biztalk mapping
My Problem:
I have xml source file which has invoice information, something like this.
-<invoice>
<invoiceNumber>1124</invoiceNumber>
+<invoiceHeader>
+<invoiceDetails>
</invoice>
<invoiceNumber>1598</invoiceNumber>
+<invoiceHeader>
+<invoiceDetails>
</invoice>
It is possible that, sometimes the subnode ie. invoiceDetails information can be missing for few invoice Numbers,but header information will be present.
Output required:
The output file (.csv) should have all invoice numbers irrespective of detail tag present or not?
Add a Looping Functoid to the Map with the source link from and the target from the Looping Functoid linked to the row element in the Flat File Schema.
It will work, trust us. :)
It depends on how is the output schema, but solution must be easy only link tag to the output.
Behind the scenes, the XSLT produced is a loop for each tag and copy that value to the output, irrespective of detail tag present or not.

how to convert an XML into an array in asp.net

i need to convert an XML into an array using asp.net.
I tried searching on the web but couldn't find the proper solution.
Can someone please help me with this
Thanks,
Alloi
I find LinqToXML helpful in these circumstances. I have a very simple XML document:
<?xml version="1.0" encoding="utf-8" ?>
<People>
<Person>
<id>1</id>
<name>Dave</name>
</Person>
<Person>
<id>2</id>
<name>Pete</name>
</Person>
<Person>
<id>3</id>
<name>Marie</name>
</Person>
</People>
And the following code that will turn it into an array of objects:
FileStream file = new FileStream("data.xml", FileMode.Open);
XDocument xmldoc = XDocument.Load(file);
var people = (from p in xmldoc.Descendants("Person")
select new
{
ID = p.Element("id").Value,
Name = p.Element("name").Value
}).ToArray();
foreach (var person in people)
{
Console.WriteLine(person.Name);
}
I think LinqToXML might be helpful in your situation. Here's a sample in vb.net (I could not find anything in csharp...): http://msdn.microsoft.com/en-us/vbasic/bb738047.aspx#convnodesarray
If you have an XSD to which the XML refers to, that probably can be a starting point on the implementation of array (or list).
A way... might help you
Read xml into dataset.
Iterate dataset on the basis of table rows and add each row entity to a list.
display list as array or list itself.
I don't know if there is a .net class that performs this action directly or not but in case there is no you have 2 options :
1 . Load XML into dataset then loop in the dataset and set elements of the array.
2 . Get XML nodes number then loop through XML and read each node element then put it in the array.
Hope that this is useful
Alloi - i think that due to the complexity inherent in xml structures, this will very much depend on the xml itself. what i'm saying is that a generic solution may be very difficult to make bomb proof, whereas a solution to a 'known' structure may be fairly straightfwd. the serialiser may allow you to save it to ToList() or similar but beyond that, it's a case of horses for sources i think. :)
jim
[edit] - link that may be useful: http://www.c-sharpcorner.com/UploadFile/chauhan_sonu57/SerializingObjects07202006065806AM/SerializingObjects.aspx
also - a nice little link showing how to convert xml->json in c# : http://www.phdcc.com/xml2json.htm

Resources