Best xml questions in January 2012

Automatically build resource class based of XML in Java

8 votes

In Android applications, resources are specified in xml documents, which automatically are built into the R class, readily accessible within the source code as strongly typed.

Is there any way I could use a similar approach for a regular Java desktop application?

What I'd like to accomplish, is both the removal of strings from the code (as a separation of "layers", more or less) and to make it easy to add support for localization, by simply telling the program to choose the xml file corresponding to the desired language.

I've googled around a bit, but the things I'm looking for seem to be drowning in results about parsing or outputting xml, rather than tools utilizing xml to generate code.

Eclipse's message bundle implementation (used by plugins for example) integrates with the Externalize Strings feature and generates both a static class and a resource properties file for your strings:

http://www.eclipse.org/eclipse/platform-core/documents/3.1/message_bundles.html

For this integration to work Eclipse needs to see org.eclipse.osgi.util.NLS on the class path. From memory, the dependencies of the libraries it was available in were a little tricky for the project I used this approach in, so I just got the source and have it as a stand-alone class in my core module (see the comments for more on that).

It provides the type safety you're looking for and the IDE features save a lot of time. I've found no downsides to the approach so far.

Edit: this is actually what ghostbust555 mentioned in the comments, but not clear in that article that this isn't limited to Eclipse plugins and you refer to your resources via static members of a messages class.

I haven't seen any mention of others using this approach with their own applications, but to me it makes complete sense given the IDE integration and type safety.

Why is my XDocument saving the declaration when I don't want it to?

7 votes

I have the following code:

class Program
{
    static void Main(string[] args)
    {
        using (var stream = File.Create(@"C:\test.xml"))
        {
            var xml =
                new XElement("root",
                    new XElement("subelement1", "1"),
                    new XElement("subelement2", "2"));

            var doc = new XDocument(xml);
            doc.Declaration = null;
            doc.Save(stream);
        }
    }
}

I am trying to get XML to save without the xml declaration, but even though I am nulling out the declaration of the XDocument, it is still being saved to the final XML.

This code is outputting:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <subelement1>1</subelement1>
  <subelement2>2</subelement2>
</root>

Instead XDocument.Save() you can use XmlWriter with XmlWriterSettings.OmitXmlDeclaration set to true

using System.IO;
using System.Xml;
using System.Xml.Linq;

XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Indent = true;

using (var stream = File.Create(@"C:\test.xml"))
using (XmlWriter xw = XmlWriter.Create(stream, xws))
{
    var xml = new XElement(
        "root",
        new XElement("subelement1", "1"),
        new XElement("subelement2", "2"));

    xml.Save(xw);
}

Convert string to variable name

6 votes

I have an XML file, I have a node and I read all ChildNodes. The name of the childNode match to a variable I have to set with the value of this childNode.

In the loop, I'd like set :

  • myvar1 to MyValue1
  • myvar2 to MyValue2

The C# Code :

protected string myvar1;
protected string myvar2;

The XML content look like this :

<parameters>
 <myvar1>MyValue1</myvar1>
 <myvar2>MyValue2</myvar2>
</parameters>

C# set variables :

    foreach (var item in xmlParamInstallation.SelectNodes("parameters")[0].ChildNodes)
    {
        ??????
    }

Any idea ?

Thanks,

UPDATE 1: the value "field" in the loop is null all the time.

public class ParametersTest
{
    public string myvar1 { get; set; }
    public string myvar2 {get; set;}
}

var type = typeof(ParametersTest);
foreach (XmlNode item in xmlParamInstallation.SelectNodes("parameters")[0].ChildNodes)
{

    var field = type.GetField(item.LocalName);
    field.SetValue(field, item.InnerText);
}

You can do it using Reflection:

var type = typeof(SomeClass);
var field = type.GetField(item.Name);
field.SetValue(null, item.InnerText);

RE: UPDATE 1

var parameters = new ParametersTest();
var type = parameters.GetType();

var s = @"<parameters>
            <MyVar1>MyValue1</MyVar1>
            <MyVar2>MyValue2</MyVar2>
           </parameters>";

var xmlParamInstallation = new XmlDocument();
xmlParamInstallation.LoadXml(s);

foreach (XmlNode item in xmlParamInstallation.SelectNodes("parameters")[0].ChildNodes)
{

    var field = type.GetProperty(item.LocalName);
    field.SetValue(parameters, item.InnerText, null);
}

Use XML Literals in C#?

6 votes

Is it possible to add literal XML data within a C# code file? I'm currently using a multiline string literal but it gets messy as you can see. Any better way of doing this?

string XML = @"<?xml version=""1.0"" encoding=""utf-8""?>
<customUI xmlns=""http://schemas.example.com/customui"">
    <toolbar id=""save"">
    </toolbar>
</customUI>";

XML literals are a feature of VB.NET, not C#.

What you have posted is as close as you can get in C#.

You may want to consider replacing the embedded double quotes with single quotes though (as both types are valid XML).

For larger amounts of XML you may want to consider the answer from Marc - using an XML file (loaded once and stored in memory), so you can take advantage of the XML editor.

XML Schema How to Declare Price and Currency

6 votes

I'm creating an XML schema that stores information about houses.

I want to store the price and the currency.

It makes sense in my mind to declare this by having the currency as an attribute of the price element.

Also, I want to restrict the values that can be entered as the currency to pounds, euros or dollars.

EG:

<price currency="euros">10000.00</price>

So at the moment I'm declaring this in my XML Schema as:

<!-- House Price, and the currency as an attribute -->
<xs:element name="price">
    <xs:complexType>
        <xs:attribute name="currency">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="pounds" />
                    <xs:enumeration value="euros" />
                    <xs:enumeration value="dollars" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
</xs:element>

The issue that I have with this:

  • I'm not exactly sure if this will restrict the attribute element to pounds, euros or dollars
  • I can't seem to specify a type on the price to a double, as I would like due to the error:

    Element 'price' has both a 'type' attribute and a 'anonymous type' child. Only one of these is allowed for an element.

Should I just keep it simple and declare them as separate elements:

<price>10000.00</price>
<currency>euros</currency>

...or am I on the right path?

The following defines the price element to have an xs:double value with a currency attribute who's values are restricted to a value of either: pounds, euros, or dollars.

 <xs:element name="price">
        <xs:complexType>
            <xs:simpleContent>
                <xs:extension base="xs:double">
                    <xs:attribute name="currency">
                        <xs:simpleType>
                            <xs:restriction base="xs:string">
                                <xs:enumeration value="pounds" />
                                <xs:enumeration value="euros" />
                                <xs:enumeration value="dollars" />
                            </xs:restriction>
                        </xs:simpleType>
                    </xs:attribute>
                </xs:extension>
            </xs:simpleContent>
        </xs:complexType>
    </xs:element>

findViewById(int) returns null on one specific button in Android 3.1 other versions its fine

6 votes

it's my first question but i'm trying to ask correctly.

As the title says only on one button and only in android 3.1 findViewById(int) returns null. Testing on Android 2.2 it works and all other buttons are found in both Android versions. It finds buttons before this specific line and afterwards.

codesnippet:

public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonInfo = (Button)findViewById(R.id.buttonInfo);//fine
buttonInfo.setOnClickListener(this);
...
Button buttonCallOpScreen = (Button)findViewById(R.id.buttonCallOpScreen);//always returns null in android 3.1
...
Button buttonTakePicture = (Button)findViewById(R.id.buttonTakePictureMain);//fine
buttonTakePicture.setOnClickListener(this);
}

main.xml-snippet:(I do know, that i should not use px but it shall work on my device only, so thats fine for this case.)

<Button 
android:id="@+id/buttonInfo" 
android:text=""
android:layout_width="332px"
android:layout_height="100px"
android:background="@drawable/btn_team" />
...
<Button
android:id="@+id/buttonCallOpScreen"
android:text=""
android:layout_width="332px"
android:layout_height="100px"
android:background="@drawable/btn_operator" />
...
<Button 
android:id="@+id/buttonTakePictureMain" 
android:text=""
android:layout_width="80px" 
android:layout_height="80px"
android:background="@drawable/btn_take_picture"
android:layout_gravity="bottom|left" />

Any help would be appreciated, thanks so far.

greetings martin


Answer:

It turned out to be a more than ugly. As there are several persons working on this project one of seemed to have changed the name in the layout-normal/main.xml. While Android-Versions before 3.1 seem to load layout/main.xml the newer ones use layout-normal/main.xml. And as it is more than understandle if the id of that button is a different findViewById(int) has to return null.

Sry for bothering you with that and thanks for the comments!

As i do have less than 100reputation I can't answer my own question to close it, if anyone could post this answer i would accept it, thanks.

greetings martin

The following answer was discovered by the person who asked the question. The details are:

As there are several persons working on this project one of seemed to have changed the name in the layout-normal/main.xml. While Android-Versions before 3.1 seem to load layout/main.xml the newer ones use layout-normal/main.xml. And as it is more than understandle if the id of that button is a different findViewById(int) has to return null.

translating one string pattern into another string pattern using XSLT

5 votes

I have my source XML like below

<contents>
  <content>AuthorInformation</content>
  <content>PersonInformation</content>
  <content>PersonPersonalInformation</content>
  <content>GurdianDetails</content>
</contents>

I would like to transform above XML into

<contents>
  <content>Author Information</content>
  <content>Person Information</content>
  <content>Person Personal Information</content>
  <content>Gurdian Details</content>
</contents>

wherever in source xml file content element data is having upper case letter I would like to prefix space inbetween. Can I have the XSLT 2.0 sample how I can achieve this.

Use a template like this:

<xsl:template match="text()">
    <xsl:value-of select="replace(., '([a-z])([A-Z])', '$1 $2')"/>
</xsl:template>

This generically performs the rule for all text content in the input. You could easily make this more specific (if there are other elements that you don't want to translate). The replace function is the key point.

cross domain issue with Jquery

5 votes

I'm trying to access webservice in another domain and it returns nothing. later I figured out it was a issue bcause of cross domain acess.

I searched online and there are so many articles but none is readable by newbie like me. :(

Can someone help me out how to access the webservice??

following is my code.

//variables for Add Contacts
var addAccountServiceUrl = 'http://crm.eyepax.net/organization.asmx?op=WriteOrg'; // Preferably write this out from server side
var OrganizationID=123;
var ParentID=123    ;
var AccountManagerID="123";
var OrganizationName="Testapple";
var IncorporationNo="23";
var PostAddress="asdfklj asldfj";
var CountryID="LK";
var VisitAddress="asldkf asldkf asldfas dfasdf";
var VisitCountryID="LK";
var VisitSwithboard="242344";
var VisitFax="234234";
var Www="http://www.eyepax.com";
var Active=true;
var RegBy=345345345345;
var ConfigurationCode="28BC9CC3@BFEBFBFF0001067A";
var Flag=1;
var LicenceOrganazationID=1;
var sErr;

function addContact()
{
//this is to be commented soon! 
alert("function called");
//update the webservice soapmesg

var soapMessage =
'<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:Body> \
    <WriteOrg xmlns="http://eyepax.crm.com/Organization"> \
      <OrganizationID>'+OrganizationID+'</OrganizationID> \
      <ParentID>'+ParentID+'</ParentID> \
      <AccountManagerID>'+AccountManagerID+'</AccountManagerID> \
      <OrganizationName>'+OrganizationName+'</OrganizationName> \
      <IncorporationNo>'+IncorporationNo+'</IncorporationNo> \
      <PostAddress>'+PostAddress+'</PostAddress> \
      <CountryID>'+CountryID+'</CountryID> \
      <VisitAddress>'+VisitAddress+'</VisitAddress> \
      <VisitCountryID>'+VisitCountryID+'</VisitCountryID> \
      <VisitSwithboard>'+VisitSwithboard+'</VisitSwithboard> \
      <VisitFax>'+VisitFax+'</VisitFax> \
      <Www>'+Www+'</Www> \
      <Active>'+Active+'</Active> \
      <RegBy>'+RegBy+'</RegBy> \
      <ConfigurationCode>'+ConfigurationCode+'</ConfigurationCode> \
      <Flag>'+Flag+'</Flag> \
      <LicenceOrganazationID>'+LicenceOrganazationID+'</LicenceOrganazationID> \
    </WriteOrg> \
  </soap:Body> \
</soap:Envelope>';

$.ajax({
url: addAccountServiceUrl,
type: "POST",
dataType: "xml",
data: soapMessage,
success: endAddContact,
error: function(jqXHR, textStatus, errorThrown) {alert("failure"); console.log(textStatus);console.log(errorThrown);},
contentType: "text/xml; charset=\"utf-8\""
});

return false;
}

function endAddContact(xmlHttpRequest, status)
{
    console.log(xmlHttpRequest);
    console.log(status);
    alert("webservice called!");
 $(xmlHttpRequest.responseXML)
    .find('WriteOrgResponse')
    .each(function()
 {
   var orgres = $(this).find('WriteOrgResult').text();
   var error = $(this).find('vstrError').text();

   alert(orgres +' -'+ error);
 });

 var a = $(xmlHttpRequest.responseXML).find('WriteOrgResult');
 var b = $(xmlHttpRequest.responseXML).find('vstrError');
 console.log("a"+a.text());
 console.log("b"+b.text());
}

Browsers do not allow cross-domain AJAX calls. Only cross-domain JSONP requests are allowed.

To use JSONP requests, you have to change the dataType property to jsonp. This means however you can not request XML, but JSONP only.


A bit about JSONP:

The <script> tag bypasses the cross-domain limitations. Which means that you can use that tag to get data from other servers. That tag doesn't support all kinds of languages, hence XML is not supported.

JSONP is basically JSON, but with a function call around it like this:

functionname({"property":"value"})

I can see you wondering: "What is that functionname doing there?"

That's EXACTLY the difference with JSON. Because the function is wrapped around it, you can use the actual data!

<script type="text/javascript">
var functionname = function(json) {
    alert(json.property);
}
</script>
<script type="text/javascript" src="http://www.domain.com/jsonp"></script>

If you replace the second script tag with the response content, it'll all make sense:

<script type="text/javascript">
var functionname = function(json) {
    alert(json.property);
}

functionname({"property":"value"});
</script>

Believe it or not, but this minor difference actually enables us to make cross-domain requests much safer.

Another thread about JSONP

Remove specific nodes under the XML root?

5 votes

My XML is below;

<XML ID="Microsoft Search Thesaurus">
 <thesaurus xmlns="x-schema:tsSchema.xml">
   <diacritics_sensitive>1</diacritics_sensitive>
   <expansion>
     <sub>Internet Explorer</sub>
     <sub>IE</sub>
     <sub>IE5</sub>
   </expansion>
   <expansion>
     <sub>run</sub>
     <sub>jog</sub>
   </expansion>
 </thesaurus>
</XML>

I want to remove the "expansion" nodes from the XML. After removing process, it would be like that;

<XML ID="Microsoft Search Thesaurus">
 <thesaurus xmlns="x-schema:tsSchema.xml">

 </thesaurus>
</XML>

My code is below;

XDocument tseng = XDocument.Load("C:\\tseng.xml");
XElement root = tseng.Element("XML").Element("thesaurus");
root.Remove();
tseng.Save("C:\\tseng.xml");

I got an error "Object reference not set to an instance of an object." for line "root.Remove()". How can I remove the "expansion" nodes from XML file? Thanks.

Use:

Will remove only expansion elements:

XNamespace ns = "x-schema:tsSchema.xml";
tseng.Root.Element(ns + "thesaurus")
    .Elements(ns + "expansion").Remove();

Will remove all children of thesaurus:

XNamespace ns = "x-schema:tsSchema.xml";
tseng.Root.Element(ns + "thesaurus").Elements().Remove();

5 votes

Using Omni package, is it possible to store XML code inside another XML file that has its own XML data?

Like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<data>
   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <otherxml>data</otherxml>
</data>

where inside the tag data, everything should be data. Is there an escape char that prevent the parser from parsing the next data into the XML data structure?

Or Does Omni comes with support for serialization for this situation?

Any other simple ideas are also welcome.

You can use CDATA:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<data>
   <![CDATA[
   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <otherxml>data</otherxml>
   ]]>
</data>

Note when you get the value for data, it will be as a string so you'd have to run it through a new XML parser.

Here is an example code for omni:

var
  xml:IXMLDocument;
  Node:IXMLNode;
begin
  xml := CreateXMLDoc;    
  xml.SelectSingleNode('/root/data',Node);
  ShowMessage(GetNodeCData(Node,'data',''));
end;

Retrieve data from XML python

5 votes

I am trying to traverse the Google XML to retrieve about 6 fields. I am using gdata provided by Google to pull the XML feed for the user profiles in my Google Apps Domain. This is the result:

<?xml version="1.0"?>
-<ns0:feed ns1:etag="W/"LIESANDCRAPfyt7I2A9WhHERE."" xmlns:ns4="http://www.w3.org/2007/app" xmlns:ns3="http://schemas.google.com/contact/2008" xmlns:ns2="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:ns1="http://schemas.google.com/g/2005" xmlns:ns0="http://www.w3.org/2005/Atom">
    <ns0:updated>2012-01-25T14:52:12.867Z</ns0:updated>
    <ns0:category term="http://schemas.google.com/contact/2008#profile" scheme="http://schemas.google.com/g/2005#kind"/>
    <ns0:id>domain.com</ns0:id>
    <ns0:generator version="1.0" uri="http://www.google.com/m8/feeds">Contacts</ns0:generator>
    <ns0:author>
        <ns0:name>domain.com</ns0:name>
    </ns0:author>
    <ns0:link type="text/html" rel="alternate" href="http://www.google.com/"/>
    <ns0:link type="application/atom+xml" rel="http://schemas.google.com/g/2005#feed" href="https://www.google.com/m8/feeds/profiles/domain/domain.com/full"/>
    <ns0:link type="application/atom+xml" rel="http://schemas.google.com/g/2005#batch" href="https://www.google.com/m8/feeds/profiles/domain/domain.com/full/batch"/>
    <ns0:link type="application/atom+xml" rel="self" href="https://www.google.com/m8/feeds/profiles/domain/domain.com/full?max-results=300"/>
    <ns2:startIndex>1</ns2:startIndex>
    <ns2:itemsPerPage>300</ns2:itemsPerPage>
    <ns0:entry ns1:etag=""CRAPQR4KTit7I2A4"">
        <ns0:category term="http://schemas.google.com/contact/2008#profile" scheme="http://schemas.google.com/g/2005#kind"/>
        <ns0:id>http://www.google.com/m8/feeds/profiles/domain/domain.com/full/nperson</ns0:id>
        <ns1:name>
            <ns1:familyName>Person</ns1:familyName>
            <ns1:fullName>Name Person</ns1:fullName>
            <ns1:givenName>Name</ns1:givenName>
        </ns1:name>
        <ns0:updated>2012-01-25T14:52:13.081Z</ns0:updated>
        <ns1:organization rel="http://schemas.google.com/g/2005#work" primary="true">
            <ns1:orgTitle>JobField</ns1:orgTitle>
            <ns1:orgDepartment>DepartmentField</ns1:orgDepartment>
            <ns1:orgName>CompanyField</ns1:orgName>
        </ns1:organization>
        <ns3:status indexed="true"/>
        <ns0:title>Name Person</ns0:title>
        <ns0:link type="image/*" rel="http://schemas.google.com/contacts/2008/rel#photo" href="https://www.google.com/m8/feeds/photos/profile/domain.com/nperson"/>
        <ns0:link type="application/atom+xml" rel="self" href="https://www.google.com/m8/feeds/profiles/domain/domain.com/full/nperson"/>
        <ns0:link type="application/atom+xml" rel="edit" href="https://www.google.com/m8/feeds/profiles/domain/domain.com/full/nperson"/>
        <ns1:email rel="http://schemas.google.com/g/2005#other" address="nperson@gapps.domain.com"/>
        <ns1:email rel="http://schemas.google.com/g/2005#other" primary="true" address="nperson@domain.com"/>
        <ns4:edited>2012-01-25T14:52:13.081Z</ns4:edited>
    </ns0:entry>
    <ns0:title>domain.com's Profiles</ns0:title>
</ns0:feed>

I am trying to use lxml to parse the data, but it is not working out so well, this is my code:

import atom
import gdata.auth
import gdata.contacts
import gdata.contacts.client
from lxml import etree
from lxml import objectify

email = 'admin@domain.com'
password = 'password'
domain = 'domain.com'

gd_client = gdata.contacts.client.ContactsClient(domain=domain)
gd_client.ClientLogin(email, password, 'profileFeedAPI')

profiles_feed = gd_client.GetProfilesFeed('https://www.google.com/m8/feeds/profiles/domain/domain.com/full?max-results=300')

def PrintFeed(feed):
  for i, entry in enumerate(feed.entry):
    print '\n%s %s' % (i+1, entry.title.text)

print(profiles_feed)
PrintFeed(profiles_feed)

profiles_feed2=(str(profiles_feed))

root = objectify.fromstring(profiles_feed2)

print root

print root.tag
print root.text

for e in root.entry():
    print e.tag
    print e.text

I can get this to return feed and then entry, but I cannot explore any farther. ALl I need is the text form the name fields in ns1 name and the org field in ns1 organization. I am a bit lost, so any help is greatly appreciated.

I always recommend to use BeautifulSoup because of its easy to learn API:

from BeautifulSoup import BeautifulStoneSoup as Soup

soup = Soup(open(filename))
for tag in soup.findAll('ns1:name'):
    print tag.find('ns1:familyname').text
    print tag.find('ns1:fullname').text
    print tag.find('ns1:givenname').text
for tag in soup.findAll('ns1:organization'):
    print tag.find('ns1:orgtitle').text
    print tag.find('ns1:orgdepartment').text
    print tag.find('ns1:orgname').text

Example output:

Person
Name Person
Name
JobField
DepartmentField
CompanyField

Need XSLT transform to remove duplicate elements - sorted by an attribute

5 votes

I have a terrible piece of XML that I need to process through BizTalk, and I have managed to normalise it into this example below. I am no XSLT ninja, but between the web and the VS2010 debugger, I can find my way around XSL.

I now need a clever bit of XSLT to "weed out" the duplicate elements and only keep the latest ones, as decided by the date in the ValidFromDate attribute.

The ValidFromDate attribute is of the XSD:Date type.

<SomeData>
  <A ValidFromDate="2011-12-01">A_1</A>
  <A ValidFromDate="2012-01-19">A_2</A>
  <B CalidFromDate="2011-12-03">B_1</B>
  <B ValidFromDate="2012-01-17">B_2</B>
  <B ValidFromDate="2012-01-19">B_3</B>
  <C ValidFromDate="2012-01-20">C_1</C>
  <C ValidFromDate="2011-01-20">C_2</C>
</SomeData>

After a transformation I'd like to only keep these lines:

<SomeData>
  <A ValidFromDate="2012-01-19">A_2</A>
  <B ValidFromDate="2012-01-19">B_3</B>
  <C ValidFromDate="2012-01-20">C_1</C>
</SomeData>

Any clues as to how I put that XSL together? I've emptied the internet trying to look for a solution, and I have tried a lot of clever XSL sorting scripts, but none I felt took me in the right direction.

A slightly simpler and shorter XSLT 1.0 solution than that of @lwburk:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kName" match="*/*" use="name()"/>

 <xsl:template match="/">
  <xsl:apply-templates select=
   "*/*[generate-id()
       =
        generate-id(key('kName', name())[1])
       ]
   "/>
 </xsl:template>

 <xsl:template match="*/*">
  <xsl:for-each select="key('kName', name())">
   <xsl:sort select="@ValidFromDate" order="descending"/>
   <xsl:if test="position() = 1">
    <xsl:copy-of select="."/>
   </xsl:if>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<SomeData>
    <A ValidFromDate="2011-12-01">A_1</A>
    <A ValidFromDate="2012-01-19">A_2</A>
    <B CalidFromDate="2011-12-03">B_1</B>
    <B ValidFromDate="2012-01-17">B_2</B>
    <B ValidFromDate="2012-01-19">B_3</B>
    <C ValidFromDate="2012-01-20">C_1</C>
    <C ValidFromDate="2011-01-20">C_2</C>
</SomeData>

the wanted, correct result is produced:

<A ValidFromDate="2012-01-19">A_2</A>
<B ValidFromDate="2012-01-19">B_3</B>
<C ValidFromDate="2012-01-20">C_1</C>

How to get xpaths for all leaf elements from XML?

5 votes

I am wondering if is possible to create an XSLT stylesheet that would extract XPATHs for all leaf elements in a given XML file. E.g. for

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <item1>value1</item1>
    <subitem>
        <item2>value2</item2>
    </subitem>
</root>

The output would be

/root/item1
/root/subitem/item2

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" indent="no" />

    <xsl:template match="*[not(*)]">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/', name())"/>

            <xsl:if test="count(preceding-sibling::*[name() = name(current())]) != 0">
                <xsl:value-of select="concat('[', count(preceding-sibling::*[name() = name(current())]) + 1, ']')"/>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:apply-templates select="*"/>
    </xsl:template>

</xsl:stylesheet>

outputs:

/root/item1
/root/subitem/item2

How to hide unselected items on a checkboxlist?

4 votes

I have a checkboxlist which gets the data from XML file. If a user selects an item on checkboxlist, i just want to show that item and hide everything else. And beneath that, I want to add clickable text to let the use to choose something else. So if the use click on that text, the user will see the checkboxlist again with the first item selected.

Basically look like this. exampe So how do we achieve this?

Thanks so much.

require to use vb.net/and checkboxlist control as we will be databinding dynamically from database.

Here is one way. Use two Panels as container for two different CheckBoxLists. The first displays your "FROM"-Items and the latter your "TO"-Items.

The second panel is initially invisivle. Apart from the CheckBoxList it contains a LinkButton to trigger the deselection.

On BtnSelect-Click you'll add the selected items from the first to the second CheckBoxList and show it's Panel. On BtnChangeSelection-Click you only need to switch visibiliy of both Panels and select first item.

This already works with multiple selection.

ASPX (CSS is up to you):

<div>
    <asp:Panel ID="PnlChkListAcademicYear" runat="server">
        <asp:CheckBoxList ID="ChkListAcademicYear" runat="server" /><br />
        <asp:LinkButton ID="BtnSelect" Text="Select" runat= "server" ></asp:LinkButton>
    </asp:Panel>
    <asp:panel ID="PnlChkListAcademicYearActive" Visible="false" runat="server">
        <asp:CheckBoxList ID="ChkListAcademicYearActive" Enabled="false" runat="server" /><br />
        <asp:LinkButton ID="BtnChangeSelection" Text="Change selection" runat= "server" ></asp:LinkButton>
    </asp:panel>
</div>

Codebehind:

Private Sub BtnSelect_Click(sender As Object, e As System.EventArgs) Handles BtnSelect.Click
    If Me.ChkListAcademicYear.SelectedIndex <> -1 Then
        Dim selectedItems = (From item In Me.ChkListAcademicYear.Items.Cast(Of ListItem)() Where item.Selected).ToArray
        Me.ChkListAcademicYearActive.Items.Clear()
        Me.ChkListAcademicYearActive.Items.AddRange(selectedItems)
        Me.PnlChkListAcademicYearActive.Visible = True
        Me.PnlChkListAcademicYear.Visible = False
    End If
End Sub

Private Sub BtnChangeSelection_Click(sender As Object, e As System.EventArgs) Handles BtnChangeSelection.Click
    Me.ChkListAcademicYear.SelectedIndex = 0
    Me.PnlChkListAcademicYearActive.Visible = False
    Me.PnlChkListAcademicYear.Visible = True
End Sub

This is the rest of my sample-code, for the sake of completeness:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not IsPostBack Then
        BindCheckboxList()
    End If
End Sub

Private Sub BindCheckboxList()
    Me.ChkListAcademicYear.DataSource = GetData()
    Me.ChkListAcademicYear.DataTextField = "Year"
    Me.ChkListAcademicYear.DataBind()
End Sub

Private Function GetData() As DataTable
    Dim years = {"2010/2009", "2009/2008", "2008/2007", "2007/2006", "2006/2005", "2005/2004", "2004/2003"}
    Dim tbl = New DataTable
    tbl.Columns.Add(New DataColumn("Year"))
    For Each y In years
        tbl.Rows.Add(y)
    Next
    Return tbl
End Function

Ignoring the null value in XML Serialization

4 votes

I have a piece of xml that looks something like

  <SubscriptionProduct>
    <SubscriptionProductIdentifier>
      <SubscriptionProductIdentifierType>
        <SubscriptionProductIDType>01</SubscriptionProductIDType>
        <ID>123456</ID>
        <Value>AAAA</Value>
      </SubscriptionProductIdentifierType>
      <SubscriptionProductIdentifierType xsi:nil="true" />
    </SubscriptionProductIdentifier>
    <SubscriptionProductDescription />
  </SubscriptionProduct>

As you can see the SubscriptionProductIdentifierType is a collection and in this case only contains one item.
How do I ignore the second empty item?

I've tried adding the xml ignore, however it removes the entire collection and I only want the second item in the collection removed if there is no data.

[System.Xml.Serialization.XmlIgnoreAttribute()]
public SubscriptionProductIdentifierType[] SubscriptionProductIdentifier {
    get {
        return this.subscriptionProductIdentifierField;
    }
    set {
        this.subscriptionProductIdentifierField = value;
    }
}

Any help would be very much appreciated.

Kind Regards Zal

There is not one item in your collection but two, one of which is null

just filter null items during addition, or even before return, depending on your business logic

public SubscriptionProductIdentifierType[] SubscriptionProductIdentifier {
    get {
        return this.subscriptionProductIdentifierField.Where(s=>s!=null).ToArray();
    }
...
}

Hope this helps