I need to transform the following input file
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<wsa:Action>http://worksite.imanage.com/SearchDocumentsResponse</wsa:Action>
<wsa:MessageID>urn:uuid:b9b79a0f-b4de-4686-9c54-51c5a7f99331</wsa:MessageID>
<wsa:RelatesTo>urn:uuid:8e88f531-8369-4557-80bf-e8a9835d8eb3</wsa:RelatesTo>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsse:Security>
<wsu:Timestamp wsu:Id="Timestamp-ea526ce6-ca66-4aaf-aae9-cf2fe8d5cbad">
<wsu:Created>2011-06-01T07:09:20Z</wsu:Created>
<wsu:Expires>2011-06-01T07:14:20Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</env:Header>
<soap:Body>
<SearchDocumentsResult xmlns="http://worksite.imanage.com">
<Documents>
<Document>
<ObjectID>!nrtdms:0:!session:PTHT096:!database:Technical:!document:803226,1:</ObjectID>
<Database>Technical</Database>
<Profile>
<ProfileItem>
<AttributeID>imProfileDocNum</AttributeID>
<Value>803226</Value>
</ProfileItem>
<ProfileItem>
<Attr开发者_如何学PythonibuteID>imProfileDescription</AttributeID>
<Value>TC-D60-1087 - Compressor C-301C Installation Work Platform General Arrangement</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileVersion</AttributeID>
<Value>1</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileCustom3</AttributeID>
<Value>CV</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileDatabase</AttributeID>
<Value>Technical</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileExtension</AttributeID>
<Value>ACROBAT</Value>
</ProfileItem>
</Profile>
</Document>
</Documents>
</SearchDocumentsResult>
</soap:Body>
</soap:Envelope>
into the following output file
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<wsa:Action>http://worksite.imanage.com/SearchDocumentsResponse</wsa:Action>
<wsa:MessageID>urn:uuid:b9b79a0f-b4de-4686-9c54-51c5a7f99331</wsa:MessageID>
<wsa:RelatesTo>urn:uuid:8e88f531-8369-4557-80bf-e8a9835d8eb3</wsa:RelatesTo>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsse:Security>
<wsu:Timestamp wsu:Id="Timestamp-ea526ce6-ca66-4aaf-aae9-cf2fe8d5cbad">
<wsu:Created>2011-06-01T07:09:20Z</wsu:Created>
<wsu:Expires>2011-06-01T07:14:20Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</env:Header>
<soap:Body>
<SearchDocumentsResult xmlns="http://worksite.imanage.com">
<Documents>
<Document>
<ObjectID>!nrtdms:0:!session:PTHT096:!database:Technical:!document:803226,1:</ObjectID>
<Database>Technical</Database>
<Profile>
<ProfileItem>
<AttributeID>imProfileDocNum</AttributeID>
<Value>803226</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileDescription</AttributeID>
<Value>TC-D60-1087 - Compressor C-301C Installation Work Platform General Arrangement</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileVersion</AttributeID>
<Value>1</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileCustom3</AttributeID>
<Value>CV</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileDatabase</AttributeID>
<Value>Technical</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileExtension</AttributeID>
<Value>pdf</Value>
</ProfileItem>
</Profile>
</Document>
</Documents>
</SearchDocumentsResult>
</soap:Body>
</soap:Envelope>
I have written the following stylesheet to do the job
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:soap = "http://www.w3.org/2003/05/soap-envelope"
xmlns:w = "http://worksite.imanage.com"
exclude-result-prefixes="#all"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="element()">
<xsl:copy>
<xsl:apply-templates select="@*,node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="attribute()|text()|comment()|processing-instruction()">
<xsl:copy/>
</xsl:template>
<xsl:template match = "//w:ProfileItem[6]/child::w:Value">
<xsl:call-template name="changeDocumentExtension"/>
</xsl:template>
<xsl:template name = "changeDocumentExtension">
<xsl:variable
name="iManageExtension"
as = "xs:string"
select="//w:AttributeID[. = 'imProfileExtension']/following::w:Value"
/>
<xsl:choose>
<xsl:when test="$iManageExtension eq 'ACROBAT'">
<Value>pdf</Value>
</xsl:when>
<xsl:when test="$iManageExtension eq 'ANSI'">
<Value>txt</Value>
</xsl:when>
<xsl:when test="$iManageExtension eq 'EXCEL'">
<Value>xsl</Value>
</xsl:when>
<xsl:when test="$iManageExtension eq 'EXCELX'">
<Value>xslx</Value>
</xsl:when>
<xsl:when test="$iManageExtension eq 'PDF230'">
<Value>pdf</Value>
</xsl:when>
<xsl:when test="$iManageExtension eq 'WORD'">
<Value>doc</Value>
</xsl:when>
<xsl:when test="$iManageExtension eq 'WORDX'">
<Value>docx</Value>
</xsl:when>
<xsl:when test="$iManageExtension eq 'WORDXT'">
<Value>docx</Value>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
This is the output that I get
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<wsa:Action>http://worksite.imanage.com/SearchDocumentsResponse</wsa:Action>
<wsa:MessageID>urn:uuid:b9b79a0f-b4de-4686-9c54-51c5a7f99331</wsa:MessageID>
<wsa:RelatesTo>urn:uuid:8e88f531-8369-4557-80bf-e8a9835d8eb3</wsa:RelatesTo>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsse:Security>
<wsu:Timestamp wsu:Id="Timestamp-ea526ce6-ca66-4aaf-aae9-cf2fe8d5cbad">
<wsu:Created>2011-06-01T07:09:20Z</wsu:Created>
<wsu:Expires>2011-06-01T07:14:20Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</env:Header>
<soap:Body>
<SearchDocumentsResult xmlns="http://worksite.imanage.com">
<Documents>
<Document>
<ObjectID>!nrtdms:0:!session:PTHT096:!database:Technical:!document:803226,1:</ObjectID>
<Database>Technical</Database>
<Profile>
<ProfileItem>
<AttributeID>imProfileDocNum</AttributeID>
<Value>803226</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileDescription</AttributeID>
<Value>TC-D60-1087 - Compressor C-301C Installation Work Platform General Arrangement</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileVersion</AttributeID>
<Value>1</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileCustom3</AttributeID>
<Value>CV</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileDatabase</AttributeID>
<Value>Technical</Value>
</ProfileItem>
<ProfileItem>
<AttributeID>imProfileExtension</AttributeID>
<Value xmlns="">pdf</Value>
</ProfileItem>
</Profile>
</Document>
</Documents>
</SearchDocumentsResult>
</soap:Body>
</soap:Envelope>
I would like to get some help with the following issues:
There is an unwanted xmlns="" element in the output that can't be removed using the exclude-result-prefixes attribute. I don't know how to get rid of it.
The stylesheet has two long XPaths. They do the job and point to the right elements but I can't help but cringe every time I look at them. If someone could offer a shorter, cleaner alternative, I'd really appreciate it.
Simplify XPath
I suggest you to include in your transform a declaration with prefix for the default namespaces. For example for
<SearchDocumentsResult xmlns="http://worksite.imanage.com">
you can add w
prefix in the stylesheet element:
<xsl:stylesheet
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:soap = "http://www.w3.org/2003/05/soap-envelope"
xmlns:w = "http://worksite.imanage.com"
exclude-result-prefixes="#all"
version="2.0">
This will make easier for you select elements in the namespace, thus making possible to avoid XPath match against namespace-uri()
and simplifying your XPath.
About XPath, how much your selection must be absolute? For example the following worked the same for me:
"/soap:Envelope/soap:Body[1]/w:SearchDocumentResult/*[1]/*[1]/*[1]/*[6]/*[1]"
But you can also use:
"/soap:Envelope/soap:Body[1]/w:SearchDocumentResult//w:Value[1]"
Remove Empty Namespace
To get rid of the empty namespace appearing in the Value
element, you need to fix your stylesheet so that each Value
element is correctly located in the namespace. Example:
<xsl:when test="$iManageExtension eq 'ACROBAT'">
<xsl:element
name="Value"
namespace="http://worksite.imanage.com">
pdf
</xsl:element>
In this way the system will usually output the element without the namespace.
Further Note about Simplifying XPath
Note that in certain situations, where mostly you want to manage a specific namespace, you can simply do:
<xsl:stylesheet
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:soap = "http://www.w3.org/2003/05/soap-envelope"
exclude-result-prefixes="#all"
xpath-default-namespace="http://worksite.imanage.com"
version="2.0">
and work without namespace prefix.
The following stylesheet does the job:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:w = "http://worksite.imanage.com"
exclude-result-prefixes="#all"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="element()">
<xsl:copy>
<xsl:apply-templates select="@*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="attribute()|text()|comment()|processing-instruction()">
<xsl:copy/>
</xsl:template>
<xsl:template match = "//w:ProfileItem[6]/child::w:Value">
<xsl:element name="{local-name()}" namespace="http://worksite.imanage.com">
<xsl:call-template name="changeDocumentExtension"/>
</xsl:element>
</xsl:template>
<xsl:template name="changeDocumentExtension">
<xsl:variable
name="iManageExtension"
as="xs:string"
select="//w:AttributeID[. = 'imProfileExtension']/following::w:Value"/>
<xsl:choose>
<xsl:when test="$iManageExtension eq 'ACROBAT'"> pdf </xsl:when>
<xsl:when test="$iManageExtension eq 'ANSI'"> txt </xsl:when>
<xsl:when test="$iManageExtension eq 'EXCEL'"> xsl </xsl:when>
<xsl:when test="$iManageExtension eq 'EXCELX'"> xslx </xsl:when>
<xsl:when test="$iManageExtension eq 'HTML'"> htm </xsl:when>
<xsl:when test="$iManageExtension eq 'JPEG'"> jpg </xsl:when>
<xsl:when test="$iManageExtension eq 'PDF230'"> pdf </xsl:when>
<xsl:when test="$iManageExtension eq 'PPT'"> ppt </xsl:when>
<xsl:when test="$iManageExtension eq 'PPTX'"> pptx </xsl:when>
<xsl:when test="$iManageExtension eq 'WORD'"> doc </xsl:when>
<xsl:when test="$iManageExtension eq 'WORDX'"> docx </xsl:when>
<xsl:when test="$iManageExtension eq 'WORDXT'"> docx </xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
精彩评论