0

I have a source xml that contains a list of element which may or may not exists in target xml and target xml has some other xml element. The requirement is to update the second xml with the rule :loop at the element in the first xml. if node exists in the target xml then update the value, otherwise add the node to the target xml. I could hard code on field name f1 and f2 and f3 for my example below. But I am wondering if it is possible to make it generic so to have a piece of transformation code really saying "loop at the element in the first xml. if node exists in the target xml then update the value, otherwise add a new node" without coding on each node name?

Parameter XML

<root>
<f1>1<f1>
<f2>2<f2>
<f3>3<f3>
</root>

input XML

<root>
<f1>a<f1>
<FY>Y<fY>
<fz>Z<fz>
</root>

output XML

<root>
<f1>1<f1>
<f2>2<f2>
<f3>3<f3>
<FY>Y<fY>
<fz>Z<fz>
</root>

I am using XSLT Version 1.0

<xsl:param name="SourceData" />
    <xsl:variable name="Source_xml" select="parse-xml($SourceData)" />

and then

 <xsl:template match="f1">
  <f1><xsl:value-of select="$Source_xml//f1"/></f1>
 </xsl:template>
 <xsl:template match="f2">
  <f2><xsl:value-of select="$Source_xml//f2"/></f2>
 </xsl:template>
 <xsl:template match="f3">
  <f3><xsl:value-of select="$Source_xml//f3"/></f3>
 </xsl:template>
3
  • 1
    The claim "I am using XSLT Version 1.0" seems complete nonsense if the XSLT code use a function like parse-xml which is a function only introduced in XPath 3 and therefore usually only supported by XSLT 3 processors. Commented Sep 28, 2024 at 17:09
  • Try this as your starting point: stackoverflow.com/a/31402704/3016153. Commented Sep 28, 2024 at 17:26
  • While asking an XSLT question you need to provide a minimal reproducible example: (1) Well-formed input XML with all relevant namespaces. (2) Your logic, and complete executable XSLT stylesheet that tries to implement it. (3) Desired output, based on the sample XML in the #1 above. (4) XSLT processor and its conformance with the XSLT standards: 1.0, 2.0, 3.0, or 4.0. Commented Sep 29, 2024 at 0:19

1 Answer 1

2

Given that (if parse-xml() works) you are using XSLT 3.0, you can use the xsl:merge instruction:

<root>
  <xsl:merge>
    <xsl:merge-source 
           for-each-source="'doc1.xml', 'doc2.xml'"
           select="/*/*">
      <xsl:merge-key select="name()" order="ascending"/>
    </xsl:merge-source>
    <xsl:merge-action>
      <xsl:copy-of select="current-merge-group()[1]"/>
    </xsl:merge-action>
  </xsl:merge>
</root>

This assumes that both inputs are sorted by name. If not, there is an option sort-before-merge to force this.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.