Best xml questions in June 2011

Why is it that regex cannot match an XML element ?

6 votes

This article argues that regular expressions cannot match nested structures because regexes are finite automatons.

He then offers a list of problems in which the answer states that the following cannot be solved using regexes:

  1. matching an XML element
  2. matching a C/VB/C# math expression
  3. matching a valid regex

Since 2 & 3 can conceivably contain brackets; this nesting is unsolvable for regexes. But why is it impossible to match an XML element ? (He didn't provide examples).

You can match a limited subset of HTML tags, if you know in advance the tags to be matched.

But you can't (reliably or nicely) parse arbitrary HTML. It is not a regular language.

Mapping xml values to enum type.

6 votes

I need to parse a XML file which I get from third party to C# objects. Some of the XML I receive have enumeration values which I want to store in an enum type.

For example, I've got the following xsd of the xml file:

<xsd:simpleType name="brandstof">
  <xsd:restriction base="xsd:string">
    <!--  Benzine --> 
    <xsd:enumeration value="B" /> 
    <!--  Diesel --> 
    <xsd:enumeration value="D" /> 
    <!--  LPG/Gas --> 
    <xsd:enumeration value="L" /> 
    <!--  LPG G3 --> 
    <xsd:enumeration value="3" /> 
    <!--  Elektrisch --> 
    <xsd:enumeration value="E" /> 
    <!--  Hybride --> 
    <xsd:enumeration value="H" /> 
    <!--  Cryogeen --> 
    <xsd:enumeration value="C" /> 
    <!--  Overig --> 
    <xsd:enumeration value="O" /> 
  </xsd:restriction>
</xsd:simpleType>  

I want to map this to an enum and I got this far:

public enum Fuel
{
    B,
    D,
    L,
    E,
    H,
    C,
    O
}

The problem I have is that the xml can contain a value of 3 which I can't seem to put in the enum type. Is there any solution to put this value in the enum.

I also can get other values with a - or a / in them and which I want to put in an enum type.
Anu suggestions are welcome!

You can parse the xml attribute value back to an enum type with:

var value = Enum.Parse(typeof(Fuel), "B");

But I don't think you will get really far with your "special" values (3, a/ etc.). Why don't you define your enum as

enum Fuel
{
    Benzine,
    Diesel,
    // ...
    Three,
    ASlash,
    // ...
}

And write a static method to convert a string to an enum member?

One thing you could look into for implementing such a method would be to add custom attributes to the enum members containing their string representation - if a value doesn't have an exact counterpart in the enumeration, look for a member with the attribute.

Creating such an attribute is easy:

/// <summary>
/// Simple attribute class for storing String Values
/// </summary>
public class StringValueAttribute : Attribute
{
    public string Value { get; private set; }

    public StringValueAttribute(string value)
    {
        Value = value;
    }
}

And then you can use them in your enum:

enum Fuel
{
    [StringValue("B")]        
    Benzine,
    [StringValue("D")]
    Diesel,
    // ...
    [StringValue("3")]
    Three,
    [StringValue("/")]
    Slash,
    // ...
}

These two methods will help you parse a string into an enum member of your choice:

    /// <summary>
    /// Parses the supplied enum and string value to find an associated enum value (case sensitive).
    /// </summary>
    public static object Parse(Type type, string stringValue)
    {
        return Parse(type, stringValue, false);
    }

    /// <summary>
    /// Parses the supplied enum and string value to find an associated enum value.
    /// </summary>
    public static object Parse(Type type, string stringValue, bool ignoreCase)
    {
        object output = null;
        string enumStringValue = null;

        if (!type.IsEnum)
        {
            throw new ArgumentException(String.Format("Supplied type must be an Enum.  Type was {0}", type));
        }

        //Look for our string value associated with fields in this enum
        foreach (FieldInfo fi in type.GetFields())
        {
            //Check for our custom attribute
            var attrs = fi.GetCustomAttributes(typeof (StringValueAttribute), false) as StringValueAttribute[];
            if (attrs != null && attrs.Length > 0)
            {
                enumStringValue = attrs[0].Value;
            }                       

            //Check for equality then select actual enum value.
            if (string.Compare(enumStringValue, stringValue, ignoreCase) == 0)
            {
                output = Enum.Parse(type, fi.Name);
                break;
            }
        }

        return output;
    }

And while I'm at it: here is the other way round ;)

    /// <summary>
    /// Gets a string value for a particular enum value.
    /// </summary>
    public static string GetStringValue(Enum value)
    {
        string output = null;
        Type type = value.GetType();

        if (StringValues.ContainsKey(value))
        {
            output = ((StringValueAttribute) StringValues[value]).Value;
        }
        else
        {
            //Look for our 'StringValueAttribute' in the field's custom attributes
            FieldInfo fi = type.GetField(value.ToString());
            var attributes = fi.GetCustomAttributes(typeof(StringValueAttribute), false);
            if (attributes.Length > 0)
            {
                var attribute = (StringValueAttribute) attributes[0];
                StringValues.Add(value, attribute);
                output = attribute.Value;
            }

        }
        return output;

    }

How to comment a line of a XML file in C# with System.XML

6 votes

I need to comment and uncomment the 4th line of this XML file using System.XML properties:

<?xml version="1.0" encoding="utf-8"?>
    <configuration>    
        <system.web>
            <customErrors mode="On" defaultRedirect="som_url_here" />
        </system.web>
    </configuration>

Desired output:

<!-- <customErrors mode="On" defaultRedirect="som_url_here" /> -->

It's possible to achieve this without using a file reader/etc?

The node:

XmlNode xmlNodoCE = docWebConfig.DocumentElement.SelectSingleNode("system.web/customErrors");

You need to

  • load the file into an XmlDocument,
  • retrieve the node you want to comment,
  • create a comment node containing the XML content of your original node,
  • add this comment to the original's parent node just before the original node
  • remove it from its parent,
  • write the XmlDocument to a file (the same one).

    String xmlFileName = "Sample.xml";
    
    // Find the proper path to the XML file
    String xmlFilePath = this.Server.MapPath(xmlFileName);
    
    // Create an XmlDocument
    System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
    
    // Load the XML file in to the document
    xmlDocument.Load(xmlFilePath);
    
    // Get the target node using XPath
    System.Xml.XmlNode elementToComment = xmlDocument.SelectSingleNode("/configuration/system.web/customErrors");
    
    // Get the XML content of the target node
    String commentContents = elementToComment.OuterXml;
    
    // Create a new comment node
    // Its contents are the XML content of target node
    System.Xml.XmlComment commentNode = xmlDocument.CreateComment(commentContents);
    
    // Get a reference to the parent of the target node
    System.Xml.XmlNode parentNode = elementToComment.ParentNode;
    
    // Replace the target node with the comment
    parentNode.ReplaceChild(commentNode, elementToComment);
    
    xmlDocument.Save(xmlFilePath);
    

Eclipse AndroidManifest.xml format

6 votes

When I format the xml using Ctrl+Shift+F the result is being like that:

This is the result of Ctrl+Shift+F

But It would be nice if something can make xml like that:

But I want to have this

Is there any way to format the formatting on eclipse?

THIS could help

How can I specify an element to have an attribute that states how many children it contains in an XML Schema?

6 votes

Is it even possible?

  • I know it’s possible to do a restriction based on regex, but that’s not it
  • I know it’s possible to declare an attribute as a foreign key calculated by an XPath, but it seems it has to be unique

Exemple:

<root children="2">
  <child/>
  <child/>
</root>

Thanks !

W3C Schema 1.0 doesn't have the ability to constrain the attribute values based upon the instance document.

Schematron is a great tool for validating that documents adhere to such custom validation scenarios.

For example:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron">
    <pattern>
        <rule context="root[@children]">
            <assert 
                id="children-value" 
                test="@children=count(child)" 
                flag="error">
                The root/@children value must be equal to the number of child elements.
                </assert>
            </rule>
    </pattern>
</schema>

Problems animating COLLADA Model

6 votes

I have some problems animating a loaded COLLADA Model. I've written my own parser and now I also want to write my own draw routine as well. The problem ist, that as soon as I enable the animation on my model, the hands, legs and the head is stretched away from the origin of the model. (The loader is implemented based on the tutorial here: COLLADA Tutorial)

The first thing I do in my draw function of the model is setup the joints matrices (not it's world matrices!) with the given targets from the read blocks, If I for example read a channel like:

<channel source="#some_sampler" target="some_joint/transform(3)(2)"/>

I will modify the matrix component (3)(2) from the joint's jointMatrix with the sid="transform" in this first step:

if( mCurrentAnimations_.size() > 0 ) {
    unsigned currentFrame = GEAR::Root::getSingleton().getFrameEvent().frame;
    bool updateTime = false;
    if( currentFrame != mLastFrameUpdate_ ) {
        if( timeSinceLastFrame < 1.0f ) 
            updateTime = true;
        mLastFrameUpdate_ = currentFrame;
    }

    /****************************************************
     * If we have an active animation,                  *
     * we animate it in each of it's defined channels   *
     ***************************************************/
    std::list<DAEAnimation*>::iterator it = mCurrentAnimations_.begin();
    while( it != mCurrentAnimations_.end() ) {
        for( int c = 0; c < (*it)->animation->channels.size(); ++c ) {
            // update the time of the channelanimation if requested
            if( updateTime ) {
                (*it)->channelStates[c].elapsedTime += timeSinceLastFrame;
            }

            GEAR::COLLADA::Channel* channel = (*it)->animation->channels[c];
            // read the two indices depending on the time we're 
            int firstKeyframeTimeIndex = 0;
            int secondKeyframeTimeIndex = 0;
            for( int i = 0; i < channel->sampler->inputSource->mFloatArray_->mCount_; ++i ) {
                float time = channel->sampler->inputSource->mFloatArray_->mFloats_[i];
                if( firstKeyframeTimeIndex == secondKeyframeTimeIndex && time > (*it)->channelStates[c].elapsedTime && i > 0) {
                    firstKeyframeTimeIndex = i-1;
                    secondKeyframeTimeIndex = i;
                    break;
                }
                if( firstKeyframeTimeIndex == secondKeyframeTimeIndex && i == channel->sampler->inputSource->mFloatArray_->mCount_-1 ) {
                    (*it)->channelStates[c].elapsedTime = 0.0f;
                    firstKeyframeTimeIndex = i;
                    secondKeyframeTimeIndex = 0;
                    break;
                }
            }
            // look what kind of TargetAccessor we have
            if( channel->targetAccessor != NULL && channel->targetAccessor->type == GEAR::MATRIX_ACCESSOR ) {
                // ok we have to read 1 value for first and second index
                float firstValue = channel->sampler->outputSource->mFloatArray_->mFloats_[firstKeyframeTimeIndex];
                float secondValue = channel->sampler->outputSource->mFloatArray_->mFloats_[secondKeyframeTimeIndex];

                float firstTime = channel->sampler->inputSource->mFloatArray_->mFloats_[firstKeyframeTimeIndex];
                float secondTime = channel->sampler->inputSource->mFloatArray_->mFloats_[secondKeyframeTimeIndex];
                float interpolateValue = 1.0f / (secondTime - firstTime) * (secondTime - (*it)->channelStates[c].elapsedTime);
                // now we calculate an linear interpolated value
                float value = (secondValue*interpolateValue) + (firstValue*(1.0-interpolateValue));

                // now we have to write this value to the Joint's Matrix
                int entry = ((COLLADA::MatrixTargetAccessor*)channel->targetAccessor)->firstAccessor*4+((COLLADA::MatrixTargetAccessor*)channel->targetAccessor)->secondAccessor;
                channel->targetJoint->matrix->jointSpaceMatrix.entries[entry] = channel->targetJoint->matrix->matrix.entries[entry] + value;
            }
        }
        ++it;
    }
}

After the jointMatrices are modified by all channels, I recalculate the joint's worldMatrices by calling the following function on the root Joint:

    void 
COLLADA::Joint::recalcWorldSpaceTransMat() {
    GEAR::Mat4 parentMat;
    if( parent != NULL )
        parentMat = parent->worldSpaceTransformationMatrix;
    // @todo Here we have to test against NULL!
    if( matrix != NULL ) 
        this->worldSpaceTransformationMatrix = parentMat * matrix->jointSpaceMatrix;
    else {
        this->worldSpaceTransformationMatrix = parentMat;
    }
    //std::cout << "Joint " << sid << " recalculated\n";
    for( int i = 0; i < mChildJoints_.size(); ++i )
        mChildJoints_[i]->recalcWorldSpaceTransMat();
}

Now everything should be ready to draw my model width the following last part of my draw function:

for( int i = 0; i < mSubMeshes_.size(); ++i ) {
    for( int k = 0; k < mSubMeshes_[i]->mSubMeshes_.size(); ++k ) {
        // first we animate it
        GEAR::DAESubMesh* submesh = mSubMeshes_[i]->mSubMeshes_[k];
        submesh->buffer->lock( true );
        {
            for( unsigned v = 0; v < submesh->buffer->getNumVertices(); ++v ) {
                // get the array of joints, which influence the current vertex
                DAEVertexInfo* vertexInfo = submesh->vertexInfo[v];
                GEAR::Vec3 vertex; // do not init the vertex with any value!
                float totalWeight = 0.0f;
                for( int j = 0; j < vertexInfo->joints.size(); ++j ) {
                    Mat4& invBindPoseMatrix = vertexInfo->joints[j]->joint->invBindPoseMatrix;
                    Mat4& transMat = vertexInfo->joints[j]->joint->worldSpaceTransformationMatrix;
                    totalWeight += vertexInfo->joints[j]->weight;
                    vertex += (transMat*invBindPoseMatrix*(submesh->skin->bindShapeMatrix*vertexInfo->vertex))*vertexInfo->joints[j]->weight;
                }
                if( totalWeight != 1.0f ) {
                    float normalizedWeight = 1.0f / totalWeight;
                    vertex *= normalizedWeight;
                }
                submesh->buffer->bufferVertexPos( v, vertex );
            }
        }
        submesh->buffer->unlock();

        mSubMeshes_[i]->mSubMeshes_[k]->buffer->draw( GEAR::TRIANGLES, 0, mSubMeshes_[i]->mSubMeshes_[k]->buffer->getNumVertices() );
    }
}

Now The problem is, that the output looks like the following: enter image description here

I'm sure to have the data loading routine implemented right, because the general animation of the walking man is visible, but the mesh is deformed: enter image description here

As I said, when I uncomment the line:

channel->targetJoint->matrix->jointSpaceMatrix.entries[entry] = channel->targetJoint->matrix->matrix.entries[entry] + value;

The animation is disabled and the model is displayed in it's standard pose: enter image description here

Now in addition when I add a normalization to the first 3 columns of the jointMatrices like this before I recalculate the joint's worldMatrix:

GEAR::Vec3 row1( matrix->jointSpaceMatrix.entries[0], matrix->jointSpaceMatrix.entries[1], matrix->jointSpaceMatrix.entries[2] );
row1.normalize();
matrix->jointSpaceMatrix.entries[0] = row1.x;
matrix->jointSpaceMatrix.entries[1] = row1.y;
matrix->jointSpaceMatrix.entries[2] = row1.z;
GEAR::Vec3 row2( matrix->jointSpaceMatrix.entries[4], matrix->jointSpaceMatrix.entries[5], matrix->jointSpaceMatrix.entries[6] );
row2.normalize();
matrix->jointSpaceMatrix.entries[4] = row2.x;
matrix->jointSpaceMatrix.entries[5] = row2.y;
matrix->jointSpaceMatrix.entries[6] = row2.z;
GEAR::Vec3 row3( matrix->jointSpaceMatrix.entries[8], matrix->jointSpaceMatrix.entries[9], matrix->jointSpaceMatrix.entries[10] );
row3.normalize();
matrix->jointSpaceMatrix.entries[8] = row3.x;
matrix->jointSpaceMatrix.entries[9] = row3.y;
matrix->jointSpaceMatrix.entries[10] = row3.z;

The Problem still exists, but this time in another output. The Man now looks like an alien :D, but this reduces the scaling: enter image description here

I do not exactly now, whether I've done the normalization the right way. Is this normaliation really needed? It isn't described in the tutorial and I also was not able to find anything related.

After all I was taken a look at the implementation of the interpolation in the code from the tutorial page. AND: They do not use any quaternions at all to intrpolate the hole matrix. What they do is the following (which does not work for me):

        Mat4 temp;

    for (int i = 0; i < 16; ++i)
        temp.entries[i] = interpolatef(matrix->jointSpaceMatrixStart.entries[i],matrix->jointSpaceMatrixFinish.entries[i],matrix->delta);

    Vec3 forward,up,right,translation;
    forward = Vec3(temp.entries[8], temp.entries[9], temp.entries[10]);
    up= Vec3(temp.entries[4], temp.entries[5], temp.entries[6]);
    right = Vec3(temp.entries[0], temp.entries[1], temp.entries[2]);

    forward.normalize();
    up.normalize();
    right.normalize();

    temp.entries[8] = forward.x; temp.entries[9] = forward.y; temp.entries[10] = forward.z;
    temp.entries[4] = up.x; temp.entries[5] = up.y; temp.entries[6] = up.z;
    temp.entries[0] = right.x; temp.entries[1] = right.y; temp.entries[2] = right.z;

    matrix->jointSpaceMatrix = GEAR::Mat4(temp);

Then I use quaternions in another approach like that (also not works for me):

        // wat we need for interpolation: rotMatStart, rotMatFinish, delta

    // create rotation matrices from our 2 given matrices
    GEAR::Mat4 rotMatStart = matrix->jointSpaceMatrixStart;
    rotMatStart.setTranslationPart( GEAR::VEC3_ZERO );
    GEAR::Mat4 rotMatFinish = matrix->jointSpaceMatrixFinish;
    rotMatFinish.setTranslationPart( GEAR::VEC3_ZERO );

    rotMatStart.transpose();
    rotMatFinish.transpose();

    // create Quaternions, which represent these 2 matrices
    float w = GEAR::Tools::sqr(1.0 + rotMatStart.entries[0] + rotMatStart.entries[5] + rotMatStart.entries[10]) / 2.0;
    float w4 = (4.0 * w);
    float x = (rotMatStart.entries[6] - rotMatStart.entries[9]) / w4 ;
    float y = (rotMatStart.entries[8] - rotMatStart.entries[2]) / w4 ;
    float z = (rotMatStart.entries[1] - rotMatStart.entries[4]) / w4 ;
    GEAR::Quaternion rotQuadStart(x, y, z, w);
    rotQuadStart.normalize();
    w = GEAR::Tools::sqr(1.0 + rotMatFinish.entries[0] + rotMatFinish.entries[5] + rotMatFinish.entries[10]) / 2.0;
    w4 = (4.0 * w);
    x = (rotMatFinish.entries[6] - rotMatFinish.entries[9]) / w4 ;
    y = (rotMatFinish.entries[8] - rotMatFinish.entries[2]) / w4 ;
    z = (rotMatFinish.entries[1] - rotMatFinish.entries[4]) / w4 ;
    GEAR::Quaternion rotQuadFinish(x, y, z, w);
    rotQuadFinish.normalize();

    // create the interpolated rotation matrix
    GEAR::Quaternion slerpedRotQuat = slerp(rotQuadStart, rotQuadFinish, matrix->delta );
    slerpedRotQuat.normalize();
    GEAR::Mat4 rotMat;
    slerpedRotQuat.createMatrix( rotMat );

    // interpolate the translation part
    GEAR::Vec3 transVecStart(0.0,0.0,0.0);
    matrix->jointSpaceMatrixStart.getTranslatedVector3D( transVecStart );
    GEAR::Vec3 transVecFinish(0.0,0.0,0.0);
    matrix->jointSpaceMatrixFinish.getTranslatedVector3D( transVecFinish );

    GEAR::Mat4 transMat;
    transMat.setTranslation( transVecFinish*matrix->delta + (transVecStart*(1.0f-matrix->delta)) );
    // now write the resulting Matrix back to the Joint
    matrix->jointSpaceMatrix = transMat * rotMat;

It will also not work for me. Nothing seems to work. I really have no idea what's going on with this.


Now after 2 days, I got it working thanks to the answer of datenwolf

I want to inform all how I got it working. Now everything seems clear and it was only a small step all the time. Now we start with the animation part. I iterate over all channels and save the starting and ending values as well as a interpolation delta value in range 0.0 1.0 to the joint, the channel animates:

if( mCurrentAnimations_.size() > 0 ) {
    unsigned currentFrame = GEAR::Root::getSingleton().getFrameEvent().frame;
    bool updateTime = false;
    if( currentFrame != mLastFrameUpdate_ ) {
        if( timeSinceLastFrame < 1.0f ) 
            updateTime = true;
        mLastFrameUpdate_ = currentFrame;
    }

    /****************************************************
     * If we have an active animation,                  *
     * we animate it in each of it's defined channels   *
     ***************************************************/
    std::list<DAEAnimation*>::iterator it = mCurrentAnimations_.begin();
    while( it != mCurrentAnimations_.end() ) {
        for( int c = 0; c < (*it)->animation->channels.size(); ++c ) {
            // update the time of the channelanimation if requested
            if( updateTime ) {
                (*it)->channelStates[c].elapsedTime += timeSinceLastFrame;
            }

            GEAR::COLLADA::Channel* channel = (*it)->animation->channels[c];
            // read the two indices depending on the time we're 
            int firstIndex = 0;
            int secondIndex = 1;
            for( int i = 0; i < channel->sampler->inputSource->mFloatArray_->mCount_; ++i ) {
                float time = channel->sampler->inputSource->mFloatArray_->mFloats_[i];
                if( time > (*it)->channelStates[c].elapsedTime ) {
                    firstIndex = i-1;
                    secondIndex = i;
                    if( firstIndex == -1 ) // set to last frame
                        firstIndex = channel->sampler->inputSource->mFloatArray_->mCount_ - 1;
                    break;
                }
                else if( i == channel->sampler->inputSource->mFloatArray_->mCount_ - 1 ) {
                    (*it)->channelStates[c].elapsedTime -= channel->sampler->inputSource->mFloatArray_->mFloats_[i];
                    firstIndex = 0;
                    secondIndex = 1;
                    break;
                }
            }
            // look what kind of TargetAccessor we have
            if( channel->targetAccessor != NULL && channel->targetAccessor->type == GEAR::MATRIX_ACCESSOR ) {
                /************************************************************************
                 * Matrix accessors, which are read from a COLLADA <channel> block      *
                 * will always target one matrix component they animate.                *
                 * Such accessors are for example:                                      *
                 * <channel source"#someSource" target="someJoint/transform(0)(2)"/>    *
                 *                                                                      *
                 * @TODO:                                                               *
                 * In a pre processing step, we have to group all channels, which       *
                 * operate on the same joint. In order to accelerate the processing of  *
                 * grouped channels, we have to expand the number of keyframes of all   *
                 * channels to the maximum of all channels.                             *
                 ************************************************************************/
                unsigned entry = ((COLLADA::MatrixTargetAccessor*)channel->targetAccessor)->index;
                float firstTime = channel->sampler->inputSource->mFloatArray_->mFloats_[firstIndex];
                float secondTime = channel->sampler->inputSource->mFloatArray_->mFloats_[secondIndex];
                // in case of matrix accessor, we write the startMatrix and the endMatrix to the Joints accessor, who finally will do the animation interpolation
                channel->targetJoint->matrix->interpolationRequired = true;
                // write out the start and end value to the jointSpaceMatrix
                // this matrix will later be interpolated
                channel->targetJoint->matrix->jointSpaceMatrixStart.entries[entry] = channel->sampler->outputSource->mFloatArray_->mFloats_[firstIndex];
                channel->targetJoint->matrix->jointSpaceMatrixFinish.entries[entry] = channel->sampler->outputSource->mFloatArray_->mFloats_[secondIndex];
                // the delta value is in the range [0.0,1.0]
                channel->targetJoint->matrix->delta = 1.0f / (secondTime - firstTime) * (secondTime - (*it)->channelStates[c].elapsedTime);
            }
        }
        ++it;
    }
}

As you can see, here is no interpolation at all. We simply cache the start and end values and a delta for all animated joints (and we also set a flag on each modified joint)

Now after all animations are done, we call the function interpolateMatrices() on all root joint:

    for( int i = 0; i < mSourceModel_->mVisualSceneLibrary_.mVisualScenes_.size(); ++i ) {
    for( int v = 0; v < mSourceModel_->mVisualSceneLibrary_.mVisualScenes_[i]->mSkeleton_.size(); ++v ) {
        if( mSourceModel_->mVisualSceneLibrary_.mVisualScenes_[i]->mSkeleton_[v]->mRootJoint_ != NULL ) {
            /************************************************************************************
             * Now we have constructed all jointSpaceMatrixces for the start and the end and    *
             * we're ready to interpolate them and to also recalculate the joint's              *
             * worldSpaceMatrix.                                                                *
             ***********************************************************************************/
            mSourceModel_->mVisualSceneLibrary_.mVisualScenes_[i]->mSkeleton_[v]->mRootJoint_->interpolateMatrices();
        }
    }
}

This isn't new, but the interesting part now is the implementation of the interpolation. Nothing qith quaternions at all:

void COLLADA::Joint::interpolateMatrices() {
if( matrix != NULL && matrix->interpolationRequired ) {

    for (unsigned i = 0; i < 16; ++i)
        matrix->jointSpaceMatrix.entries[i] = interpolatef(matrix->jointSpaceMatrixStart.entries[i],matrix->jointSpaceMatrixFinish.entries[i],matrix->delta);

    Vec3 forward,up,right,translation;
    forward = Vec3(matrix->jointSpaceMatrix.entries[8], matrix->jointSpaceMatrix.entries[9], matrix->jointSpaceMatrix.entries[10]);
    up= Vec3(matrix->jointSpaceMatrix.entries[4], matrix->jointSpaceMatrix.entries[5], matrix->jointSpaceMatrix.entries[6]);
    right = Vec3(matrix->jointSpaceMatrix.entries[0], matrix->jointSpaceMatrix.entries[1], matrix->jointSpaceMatrix.entries[2]);

    forward.normalize();
    up.normalize();
    right.normalize();

    matrix->jointSpaceMatrix.entries[8] = forward.x; matrix->jointSpaceMatrix.entries[9] = forward.y; matrix->jointSpaceMatrix.entries[10] = forward.z;
    matrix->jointSpaceMatrix.entries[4] = up.x; matrix->jointSpaceMatrix.entries[5] = up.y; matrix->jointSpaceMatrix.entries[6] = up.z;
    matrix->jointSpaceMatrix.entries[0] = right.x; matrix->jointSpaceMatrix.entries[1] = right.y; matrix->jointSpaceMatrix.entries[2] = right.z;

    matrix->jointSpaceMatrix.entries[15] = 1.0f; // this component is always 1.0! In some files, this is exported the wrong way, which causes bugs!
}
/********************************************************
 * After the interpolation is finished,                 *
 * we have to recalculate the joint's worldSpaceMatrix. *
 ********************************************************/
GEAR::Mat4 parentMat;
if( parent != NULL )
    parentMat = parent->worldSpaceTransformationMatrix;
if( matrix != NULL ) 
    worldSpaceTransformationMatrix = (parentMat * matrix->jointSpaceMatrix);
else 
    worldSpaceTransformationMatrix = parentMat;
skinningMatrix = worldSpaceTransformationMatrix*invBindPoseMatrix;

// also interpolate and recalculate all childs
for( unsigned k = 0; k < mChildJoints_.size(); ++k )
    mChildJoints_[k]->interpolateMatrices();

}

As you can see we simply intrpolate all values of the matrix and after that we normalize the upper 3 columns of the matrix. After that we immediately recalculate the worldSpaceMatrix for that Joint, as well as the complete skinning matrix to save performance. Now we're nearly complete with all. Last thing to do is to really animate the vertices and then to draw the mesh:

for( int i = 0; i < mSubMeshes_.size(); ++i ) {
    for( int k = 0; k < mSubMeshes_[i]->mSubMeshes_.size(); ++k ) {
        // first we animate it
        GEAR::DAESubMesh* submesh = mSubMeshes_[i]->mSubMeshes_[k];
        submesh->buffer->lock( true );
        {
            for( unsigned v = 0; v < submesh->buffer->getNumVertices(); ++v ) {
                // get the array of joints, which influence the current vertex
                DAEVertexInfo* vertexInfo = submesh->vertexInfo[v];
                GEAR::Vec3 vertex; // do not init the vertex with any value!
                float totalWeight = 0.0f;
                for( int j = 0; j < vertexInfo->joints.size(); ++j ) {
                    totalWeight += vertexInfo->joints[j]->weight;
                    vertex += ((vertexInfo->joints[j]->joint->skinningMatrix*(vertexInfo->vertex))*vertexInfo->joints[j]->weight);
                }
                // since it isn't guaranteed that the total weight is exactly 1.0, we have no normalize it
                // @todo this should be moved to the parser
                if( totalWeight != 1.0f ) {
                    float normalizedWeight = 1.0f / totalWeight;
                    vertex *= normalizedWeight;
                }
                submesh->buffer->bufferVertexPos( v, vertex );
            }
        }
        submesh->buffer->unlock();

        mSubMeshes_[i]->mSubMeshes_[k]->buffer->draw( GEAR::TRIANGLES, 0, mSubMeshes_[i]->mSubMeshes_[k]->buffer->getNumVertices() );
    }
}

All in all it was nearly the same as the code I started with. But now things are much clearer for me and I can start to also support <translation>, <rotation> and <scale> animations as well. Feel free to look into my implementation at gear3d.de (download the SVN trunk)

I hope this helps some people out there implementing their own solution on this wonderful topic :)

Looking at those pictures I have the impression, that your joint matrices are not normalized, i.e. the upper left 3×3 part upscales your mesh. Try what happens if you normalize the upper left 3 column vectors.

If this reduces the problem, it needs to be investigated, what part of the animation system causes this.

Is there an elegant way to count tag elements in a xml file using lxml in python?

6 votes

I could read the content of the xml file to a string and use string operations to achieve this, but I guess there is a more elegant way to do this. Since I did not find a clue in the docus, I am sking here:

Given an xml (see below) file, how do you count xml tags, like count of author-tags in the example bewlow the most elegant way? We assume, that each author appears exactly once.

<root>
    <author>Tim</author>
    <author>Eva</author>
    <author>Martin</author>
    etc.
</root>

This xml file is trivial, but it is possible, that the authors are not always listed one after another, there may be other tags between them.

If you want to count all author tags:

import lxml.etree
doc = lxml.etree.parse(xml)
count = doc.xpath('count(//author)')

Using XML files to store data

5 votes

If i'm going to use a XML file to store some information, Am I going to need a XML Parser that read/write data? Can i just use string manipulation functions and why not?

You could conceivably use string manipulation functions, as that's what XML libraries end up using anyway. XML documents are just long strings in a special format. However, unless you know a lot about XML (and what is and isn't valid XML), using an XML parser/serializer now will save you a lot of trouble later on. There are nuances to XML (namespaces, escape sequences, etc) that will cause issues in homegrown code that doesn't know how to handle them properly. And by the time you've handled all the special cases, you'll effectively have written a half-assed XML parser anyway.

Best way to structure the code for an ASP.NET MVC REST API that is decoupled from the data formats?

5 votes

I am creating a REST API in ASP.NET MVC. I want the format of the request and response to be JSON or XML, however I also want to make it easy to add another data format and easy to create just XML first and add JSON later.

Basically I want to specify all of the inner workings of my API GET/POST/PUT/DELETE requests without having to think about what format the data came in as or what it will leave as and I could easily specify the format later or change it per client. So one guy could use JSON, one guy could use XML, one guy could use XHTML. Then later I could add another format too without having to rewrite a ton of code.

I do NOT want to have to add a bunch of if/then statements to the end of all my Actions and have that determine the data format, I'm guessing there is some way I can do this using interfaces or inheritance or the like, just not sure the best approach.

Serialization

The ASP.NET pipeline is designed for this. Your controller actions don't return the result to the client, but rather a result object (ActionResult) which is then processed in further steps in the ASP.NET pipeline. You can override the ActionResult class. Note that FileResult, JsonResult, ContentResult and FileContentResult are built-in as of MVC3.

In your case, it's probably best to return something like a RestResult object. That object is now responsible to format the data according to the user request (or whatever additional rules you may have):

public class RestResult<T> : ActionResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        string resultString = string.Empty;
        string resultContentType = string.Empty;

        var acceptTypes = context.RequestContext.HttpContext.Request.AcceptTypes;

        if (acceptTypes == null)
        {
            resultString = SerializeToJsonFormatted();
            resultContentType = "application/json";
        }
        else if (acceptTypes.Contains("application/xml") || acceptTypes.Contains("text/xml"))
        {
            resultString = SerializeToXml();
            resultContentType = "text/xml";
        }

       context.RequestContext.HttpContext.Response.Write(resultString);
        context.RequestContext.HttpContext.Response.ContentType = resultContentType;
   }
}

Deserialization

This is a bit more tricky. We're using a Deserialize<T> method on the base controller class. Please note that this code is not production ready, because reading the entire response can overflow your server:

protected T Deserialize<T>()
{
    Request.InputStream.Seek(0, SeekOrigin.Begin);
    StreamReader sr = new StreamReader(Request.InputStream);
    var rawData = sr.ReadToEnd(); // DON'T DO THIS IN PROD!

    string contentType = Request.ContentType;

    // Content-Type can have the format: application/json; charset=utf-8
    // Hence, we need to do some substringing:
    int index = contentType.IndexOf(';');
    if(index > 0)
        contentType = contentType.Substring(0, index);
    contentType = contentType.Trim();

    // Now you can call your custom deserializers.
    if (contentType == "application/json")
    {
        T result = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(rawData);                
        return result;
    }
    else if (contentType == "text/xml" || contentType == "application/xml")
    {
        throw new HttpException(501, "XML is not yet implemented!");
    }
}

DataBinding to a WinForm

5 votes

I have a form (CustomerInfoForm) with 10 TextBoxes. The default Text property for each of the TextBoxes is defined at design-time. A subclass CustomerInfoForm.CustomerInfo contains properties to hold the data entered in the form. The subclass containing the data will be serialized to XML.

In the automatically generated form code, each of the text boxes has a line of code to bind the datasource to the text box

this.customerInfoBindingSource = new System.Windows.Forms.BindingSource(this.components);

Code automatically generated by the C# ide for each text box:

this.txtCustomer.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.customerInfoForm_CustomerInfoBindingSource, "CustomerName", true));
this.txtCustomer.Location = new System.Drawing.Point(60, 23);
this.txtCustomer.Name = "txtCustomer";
this.txtCustomer.Size = new System.Drawing.Size(257, 20);
this.txtCustomer.TabIndex = 0;
this.txtCustomer.Text = "CustomerName";

(I noticed that the Text property isn't set until after the DataBinding) in the IDE generated code.

When I run the project, the form is displayed with the default values in the TextBoxes. However when the SaveButton is pressed to serialize the properties in the MyForm.CustomerInfo subclass, they are all null. Since these values will only be changed from the form I was hoping that I didn't have to implement the interface INotifyPropertyChanged.

Am I missing something basic or simple?

The code for the form including the serialization of the data is attached below

using System;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization;

namespace SimpleCustomerInfo
{
    // You must apply a DataContractAttribute or SerializableAttribute
    // to a class to have it serialized by the DataContractSerializer.

    public partial class CustomerInfoForm : Form
    {
        CustomerInfo ci = new CustomerInfo();

        public CustomerInfoForm()
        {
            InitializeComponent();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(CustomerInfo));
            FileStream writer = new FileStream(@"C:\Users\Me\temp\testme.xml", FileMode.Create);
            serializer.WriteObject(writer,ci);
            writer.Close();
        }

        [DataContract(Name = "Customer", Namespace = "net.ElectronicCanvas")]
        public class CustomerInfo
        {
            [DataMember]
            public string CustomerName { get; set; }
            [DataMember]
            public PhoneInfo PhonePrimary { get; set; }
            [DataMember]
            public PhoneInfo PhoneDays { get; set; }
            [DataMember]
            public PhoneInfo PhoneEvening { get; set; }
        }

        public class PhoneInfo
        {
            public string number { get; set; }
            public string type { get; set; }
            public bool textOk { get; set; }
        }
    }
}

EDIT -- For others that may happen upon this question

using System;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization;

namespace SimpleCustomerInfo
{


    public partial class CustomerInfoForm : Form
    {
        CustomerInfo ci;

        public CustomerInfoForm()
        {
            InitializeComponent();
            ci = new CustomerInfo();
            ci.CustomerName = "My Customer Name";
            ci.PhoneDays.number = "888-888-8888";
            customerInfoForm_CustomerInfoBindingSource.DataSource = ci;

        }

        private void btnSave_Click(object sender, EventArgs e)
        {

            DataContractSerializer serializer = new DataContractSerializer(typeof(CustomerInfo));
            FileStream writer = new FileStream(@"C:\Users\me\temp\testme.xml", FileMode.Create);
            serializer.WriteObject(writer,ci);
            writer.Close();
        }
        // You must apply a DataContractAttribute or SerializableAttribute
        // to a class to have it serialized by the DataContractSerializer.
        [DataContract(Name = "Customer", Namespace = "net.ElectronicCanvas")]
        public class CustomerInfo
        {
            [DataMember]
            public string CustomerName { get; set; }
            [DataMember]
            public PhoneInfo PhonePrimary { get; set; }
            [DataMember]
            public PhoneInfo PhoneDays { get; set; }
            [DataMember]
            public PhoneInfo PhoneEvening { get; set; }

            // Constructor is needed to instantiate the PhoneInfo classes
            // within the CustomerInfo class
            public CustomerInfo()
            {
                PhonePrimary = new PhoneInfo();
                PhoneDays = new PhoneInfo();
                PhoneEvening = new PhoneInfo();
            }
        }

        public class PhoneInfo
        {
            public string number { get; set; }
            public string type { get; set; }
            public bool textOk { get; set; }
        }
    }
}

First of all you need to decide whether to use databinding or manipulate Text property directly. Those two approaches should not be mixed together.

If you want to use databinding than you are missing one line in the code:

public Form1()
{
    InitializeComponent();
    customerInfoBindingSource.DataSource = ci;  // This is the missing line
}

You need to let your customerInfoBindingSource know about the data source.

If you add this line, then the Text that is assigned in design time will be overridden by the text from your bound data source. If you want to use binding you should manipulate with the data source instead of setting Text fields directly. Like this:

public Form1()
{
    InitializeComponent();

    ci.CustomerName = "TestCustomerName";
    customerInfoBindingSource.DataSource = ci;
}

Retrieving Data From XML File

5 votes

I seem to be having a problem with retrieving XML values with C#, which I know it is due to my very limited knowledge of C# and .XML.

I was given the following XML file

<PowerBuilderRunTimes>
    <PowerBuilderRunTime>
        <Version>12</Version>
        <Files>
            <File>EasySoap110.dll</File>
            <File>exPat110.dll</File>
            <File>pbacc110.dll</File>
        </File>
     </PowerBuilderRunTime>
</PowerBuilderRunTimes>

I am to process the XML file and make sure that each of the files in the exist in the folder (that's the easy part). It's the processing of the XML file that I have having a hard time with. Here is what I have done thus far:

var runtimeXml = File.ReadAllText(string.Format("{0}\\{1}", configPath, Resource.PBRuntimes));

var doc = XDocument.Parse(runtimeXml);
var topElement = doc.Element("PowerBuilderRunTimes");
var elements = topElement.Elements("PowerBuilderRunTime");

foreach (XElement section in elements)
{
    //pbVersion is grabbed earlier. It is the version of PowerBuilder
    if( section.Element("Version").Value.Equals(string.Format("{0}", pbVersion ) ) )
    {
        var files = section.Elements("Files");

        var fileList = new List<string>();

        foreach (XElement area in files)
        {
            fileList.Add(area.Element("File").Value);
        }
    }
}

My issue is that the String List is only ever populated with one value, "EasySoap110.dll", and everything else is ignored. Can someone please help me, as I am at a loss.

Look at this bit:

var files = section.Elements("Files");

var fileList = new List<string>();

foreach (XElement area in files)
{
    fileList.Add(area.Element("File").Value);
}

You're iterating over each Files element, and then finding the first File element within it. There's only one Files element - you need to be iterating over the File elements within that.

However, there are definitely better ways of doing this. For example:

var doc = XDocument.Load(Path.Combine(configPath, Resource.PBRuntimes));
var fileList = (from runtime in doc.Root.Elements("PowerBuilderRunTime")
                where (int) runtime.Element("Version") == pbVersion
                from file in runtime.Element("Files").Elements("File")
                select file.Value)
               .ToList();

Note that if there are multiple matching PowerBuilderRunTime elements, that will create a list with all the files of all those elements. That may not be what you want. For example, you might want:

var doc = XDocument.Load(Path.Combine(configPath, Resource.PBRuntimes));
var runtime = doc.Root
                 .Elements("PowerBuilderRunTime")
                 .Where(r => (int) r.Element("Version") == pbVersion)
                 .Single();

var fileList = runtime.Element("Files")
                      .Elements("File")
                      .Select(x => x.Value)
                      .ToList();

That will validate that there's exactly one matching runtime.

How to get the selected index of a RadioGroup in Android.

5 votes

Is there an easy way to get the selected index of a RadioGroup in Android or do I have to use OnCheckedChangeListener to listen for changes and have something that holds the last index selected?

example xml:

<RadioGroup android:id="@+id/group1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
    <RadioButton android:id="@+id/radio1" android:text="option 1" android:layout_width="wrap_content" android:layout_height="wrap_content" />
    <RadioButton android:id="@+id/radio2" android:text="option 2" android:layout_width="wrap_content" android:layout_height="wrap_content" />
    <RadioButton android:id="@+id/radio3" android:text="option 3" android:layout_width="wrap_content" android:layout_height="wrap_content" />
    <RadioButton android:id="@+id/radio4" android:text="option 4" android:layout_width="wrap_content" android:layout_height="wrap_content" />
    <RadioButton android:id="@+id/radio5" android:text="option 5" android:layout_width="wrap_content" android:layout_height="wrap_content" />
</RadioGroup>

if a user selects option 3 I want to get the index, 2.

You should be able to do something like this:

int rbid = rbgrp.getCheckedRadioButtonId();
View rb = rbgrp.findViewById(rbid);
int idx = rbgrp.indexOfChild(rb);

Convert XSDs to Protos

5 votes

I have a set of services coupled with whole bunch of XSDs. Clients that use my service use XML and in the future will use protobufs. Is there a tool out there that will convert my XSDs into proto files?

The plan here is to define the interface once using XSD and then autogenerate the protos so that both interfaces remain in sync.

Protomak is a tool dedicated to exactly this task.

The lastest release supports:

  • Xsd to Proto files with support for
    • Anonymous types
    • Complex types
    • Inherited complex types
    • Restrictions for enumerations
  • Maven plugin
  • Ant build task

Disclaimer: I worked on this project