Is it possible to build an XML document from a list of XPath values and the XML XSD?
I have a list of name/value pairs that I would like to map into an XML document. My idea is this, assign each of the names an XPath like this:
Account_Number = 4294587576-32 = /my:myFields/my:Customer/my:AccountNumber
Customer_Name = John Smith = /my:myFields/my:Customer/my:Name
Customer_Address = Tampa, FL 33604 = /my:myFields/my:Customer/my:Address
Amount_Due = 129.85 = /my:myFields/my:AmountDue/my:Amount
Days_Past_Due = 54 = /my:myFields/my:AmountDue/my:DaysPastDue
Now, shouldn't I be able to take this information along with a complete sample of the XML document or the XSD and build an XML document that looks something like this:
<my:myFields>
<my:Customer>
<my:Name>John Smith</my:Name>
<my:AccountNumber>4294587576-32</my:AccountNumber>
<my:Address>Tampa, FL 33604</my:Address>
</my:Customer>
<my:AmountDue>
<my:DaysPastDue>54</my:DaysPastDue>
<my:Amount>129.85</my:Amount>
</my:AmountDue>
</my:myFields>
My question is specific to Microsoft InfoPath because I need to take the list of开发者_开发知识库 name/value pairs and build the XML data document for an InfoPath form. The technology that performs the translation does not have to be Microsoft. Java or C++ would be the best solution. Can this be done using an XSLT processor like Apache's Xalan?
Here is one suggestion, as you mention Java and XSLT I wouldn't bother with Xalan and XSLT 1.0 but instead use Saxon 9 and XSLT 2.0. Assuming you have an well-formed XML input sample and your above mapping of values to XPath expressions I would feed the mapping to an XSLT 2.0 stylesheet that generates a second stylesheet that can then be applied to the input sample. So assuming we have the file 'test2011101201.txt' as
Account_Number = 4294587576-32 = /my:myFields/my:Customer/my:AccountNumber
Customer_Name = John Smith = /my:myFields/my:Customer/my:Name
Customer_Address = Tampa, FL 33604 = /my:myFields/my:Customer/my:Address
Amount_Due = 129.85 = /my:myFields/my:AmountDue/my:Amount
Days_Past_Due = 54 = /my:myFields/my:AmountDue/my:DaysPastDue
the stylesheet
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/Transforma"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://example.com/my"
version="2.0"
exclude-result-prefixes="xs">
<xsl:param name="text-file" as="xs:string" select="'test2011101201.txt'"/>
<xsl:variable name="lines" as="xs:string*" select="tokenize(unparsed-text($text-file), '\r?\n')[normalize-space()]"/>
<xsl:output method="xml" indent="yes"/>
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:template match="/">
<axsl:stylesheet version="2.0">
<axsl:template match="@* | node()">
<axsl:copy>
<axsl:apply-templates select="@*, node()"/>
</axsl:copy>
</axsl:template>
<xsl:for-each select="$lines">
<xsl:variable name="tokens" select="tokenize(., '=')"/>
<axsl:template match="{normalize-space($tokens[3])}">
<axsl:copy>
<axsl:apply-templates select="@*"/>
<axsl:text>
<xsl:value-of select="replace($tokens[2], '(^\s+|\s+$)', '')"/>
</axsl:text>
</axsl:copy>
</axsl:template>
</xsl:for-each>
</axsl:stylesheet>
</xsl:template>
</xsl:stylesheet>
can be run to produce a second stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://example.com/my"
version="2.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/my:myFields/my:Customer/my:AccountNumber">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:text>4294587576-32</xsl:text>
</xsl:copy>
</xsl:template>
<xsl:template match="/my:myFields/my:Customer/my:Name">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:text>John Smith</xsl:text>
</xsl:copy>
</xsl:template>
<xsl:template match="/my:myFields/my:Customer/my:Address">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:text>Tampa, FL 33604</xsl:text>
</xsl:copy>
</xsl:template>
<xsl:template match="/my:myFields/my:AmountDue/my:Amount">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:text>129.85</xsl:text>
</xsl:copy>
</xsl:template>
<xsl:template match="/my:myFields/my:AmountDue/my:DaysPastDue">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:text>54</xsl:text>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
which, when applied to an input sample like
<my:myFields xmlns:my="http://example.com/my">
<my:Customer>
<my:Name></my:Name>
<my:AccountNumber></my:AccountNumber>
<my:Address></my:Address>
</my:Customer>
<my:AmountDue>
<my:DaysPastDue></my:DaysPastDue>
<my:Amount></my:Amount>
</my:AmountDue>
</my:myFields>
outputs
<?xml version="1.0" encoding="UTF-8"?><my:myFields xmlns:my="http://example.com/my">
<my:Customer>
<my:Name>John Smith</my:Name>
<my:AccountNumber>4294587576-32</my:AccountNumber>
<my:Address>Tampa, FL 33604</my:Address>
</my:Customer>
<my:AmountDue>
<my:DaysPastDue>54</my:DaysPastDue>
<my:Amount>129.85</my:Amount>
</my:AmountDue>
</my:myFields>
As I said, that requires XSLT 2.0 and an XSLT 2.0 processor like Saxon 9 to parse the text file. And whoever authors that text file needs to make sure the path expressions that the stylesheet maps into XSLT match patterns are not ambiguous.
精彩评论