Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > XML > XSLT
Password Reminder
Register
Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developersí questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old May 24th, 2018, 05:56 AM
Friend of Wrox
Points: 696, Level: 9
Points: 696, Level: 9 Points: 696, Level: 9 Points: 696, Level: 9
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2006
Location: Ennis, Clare, Ireland.
Posts: 129
Thanks: 10
Thanked 0 Times in 0 Posts
Default Copy ALL elements except one

Hi,
I have an XML file that I need to update using XSLT. The update is on 1 field only (DocumentDestinationPartner). The rest of the XML should remain the same.

Original XML file

HTML Code:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
	<Header>
		<MessageId>ABCD</MessageId>
		<Action>http://blah/</Action>
		<DocumentDestinationDivision>CBA</DocumentDestinationDivision>
		<DocumentDestinationPartner>CBA</DocumentDestinationPartner>
		<DocumentSourceDivision>TEST</DocumentSourceDivision>
		<DocumentSourcePartner>AX12PPR</DocumentSourcePartner>
		<DocumentStandard>XXXX</DocumentStandard>
		<DocumentTimeStamp>20180522133623</DocumentTimeStamp>
		<DocumentType>Document1</DocumentType>
		<DocumentUniqueId>00012</DocumentUniqueId>
	</Header>
	<Body>
		<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
			...
			...
		</MessageParts>
	</Body>
</Envelope>

I have tried updating using the following XSLT technique (I ‘borrowed’ from the web). But it doesn’t update the specific field.


XSLT file

HTML Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<!--<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>-->
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
	<!-- -->
    <!-- Identity template : copy all text nodes, elements and attributes -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- -->
    <!-- 1. Append '#D' or 'D'-->
	<xsl:template match="DocumentDestinationPartner">
		<DocumentDestinationPartner>
			<xsl:choose>
				<xsl:when test="contains(//DocumentDestinationPartner, '#D')">
					<xsl:value-of select="concat(//DocumentDestinationPartner, 'D')"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="concat(//DocumentDestinationPartner, '#D')"/>
				</xsl:otherwise>
			</xsl:choose>
		</DocumentDestinationPartner>
	</xsl:template>
	<!-- -->
    <xsl:template match="text()">
		<xsl:value-of select="normalize-space()" />
	</xsl:template>
	<!-- -->
</xsl:stylesheet>

In addition, the following attribute for the 'MessageParts' element is removed from the output (NOTE: it is the same as the Envelope attribute) which I wasn't expecting:

HTML Code:
xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"

Can anyone help please?


Thanks in advance,
__________________
Neal

A Northern Soul

Last edited by Neal; May 24th, 2018 at 06:08 AM.
Reply With Quote
  #2 (permalink)  
Old May 24th, 2018, 06:17 AM
mhkay's Avatar
Wrox Author
Points: 18,420, Level: 59
Points: 18,420, Level: 59 Points: 18,420, Level: 59 Points: 18,420, Level: 59
Activity: 100%
Activity: 100% Activity: 100% Activity: 100%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,952
Thanks: 0
Thanked 289 Times in 284 Posts
Default

Firstly, your source element is in a namespace, but you are matching elements in no namespace. Instead of match="DocumentDestinationPartner" you need match="p:DocumentDestinationPartner" where the prefix p is bound to the relevant namespace URI.

Secondly, within the template you should refer to the element currently being processed as ".", not as "//DocumentDestinationPartner". Using "//DocumentDestinationPartner" will search the whole document for elements of that name (in no namespace).

Finally, you need to create the new element in the right namespace. You can do that by writing <DocumentDestinationPartner xmlns="..."> in place of <DocumentDestinationPartner>, or simply by using xsl:copy.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
Reply With Quote
The Following User Says Thank You to mhkay For This Useful Post:
Neal (May 24th, 2018)
  #3 (permalink)  
Old May 24th, 2018, 06:22 AM
Friend of Wrox
Points: 6,666, Level: 34
Points: 6,666, Level: 34 Points: 6,666, Level: 34 Points: 6,666, Level: 34
Activity: 50%
Activity: 50% Activity: 50% Activity: 50%
 
Join Date: Nov 2007
Location: Germany
Posts: 1,240
Thanks: 0
Thanked 244 Times in 243 Posts
Default

If you move to XSLT 2 or even 3 with Saxon 9 you can ease your task of matching elements in a namespace and of copying everything except the nodes for which you write templates with
Code:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xpath-default-namespace="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
    expand-text="yes"
	version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template match="DocumentDestinationPartner">
      <xsl:copy>{. || '#D'}</xsl:copy>
  </xsl:template>
  
  <xsl:template match="DocumentDestinationPartner[contains(., '#D')]">
      <xsl:copy>{. || 'D'}</xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>
Online sample at https://xsltfiddle.liberty-development.net/pPqsHTg
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
Reply With Quote
The Following User Says Thank You to Martin Honnen For This Useful Post:
Neal (May 24th, 2018)
  #4 (permalink)  
Old May 24th, 2018, 07:36 AM
Friend of Wrox
Points: 696, Level: 9
Points: 696, Level: 9 Points: 696, Level: 9 Points: 696, Level: 9
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2006
Location: Ennis, Clare, Ireland.
Posts: 129
Thanks: 10
Thanked 0 Times in 0 Posts
Default

Thank you both...

You both helped me overcome the main problem. I still have an issue with the 'MessageParts' output. Please can either of you assist?

Michael - I have updated using your advise and the result worked great for the 'DocumentDestinationPartner'.

Martin - I am bound by company protocol and there is no plans to move to 2.0 in the near future but thanks for your help.


The updated XSLT file

HTML Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
	<!--<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>-->
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
	<!-- -->
	<xsl:template match="/">
        <xsl:apply-templates />
    </xsl:template>

    <!-- Identity template : copy all text nodes, elements and attributes -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- -->
    <!-- 1. Append '#D' or 'D'-->
	<xsl:template match="m:DocumentDestinationPartner">
		<xsl:copy>
			<xsl:choose>
				<xsl:when test="contains(., '#D')">
					<xsl:value-of select="concat(., 'D')"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="concat(., '#D')"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:copy>
	</xsl:template>
	<!-- -->
	<xsl:template match="text()">
		<xsl:value-of select="normalize-space()" />
	</xsl:template>
	<!-- -->
</xsl:stylesheet>
The MessageParts element is still outputting as
HTML Code:
<MessageParts>
i.e. it is missing the attribute. How can I resolve this to retain the original?
HTML Code:
<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">

Thanks in advance,
__________________
Neal

A Northern Soul
Reply With Quote
  #5 (permalink)  
Old May 24th, 2018, 07:42 AM
Friend of Wrox
Points: 6,666, Level: 34
Points: 6,666, Level: 34 Points: 6,666, Level: 34 Points: 6,666, Level: 34
Activity: 50%
Activity: 50% Activity: 50% Activity: 50%
 
Join Date: Nov 2007
Location: Germany
Posts: 1,240
Thanks: 0
Thanked 244 Times in 243 Posts
Default

There is nothing in your code as posted that should change the namespace of the "MessageParts" elements and indeed it is not changed, however in the input the namespace is duplicated, the XSLT serializer then eliminates the duplicated declaration. That is not something you can avoid when using XSLT.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog

Last edited by Martin Honnen; May 24th, 2018 at 07:50 AM. Reason: Had a closer look
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
How to copy all elements within the path to the root CHRD XSLT 3 September 23rd, 2010 12:41 PM
How to check whether an elements contains another elements or not? metinhoclam XSLT 5 August 14th, 2010 11:11 AM
How to copy elements to new file geek.shrek XSLT 6 January 10th, 2010 08:35 AM
copy-of select= not returning all elements jay_c XSLT 8 August 8th, 2009 02:38 PM
Chap 16 pg 574: Elements not supported Elements not known tomche BOOK: Beginning ASP.NET 3.5 : in C# and VB BOOK ISBN: 978-0-470-18759-3 1 August 6th, 2009 03:48 PM



All times are GMT -4. The time now is 07:10 AM.


Powered by vBulletin®
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.