I want to copy nodes from the source to the output if XML matches on the root node. I tried to use:
<xsl:stylesheet version="1.0" xmlns:i="http://www.somestuff.com xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/i:Root">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
With this input xml, I match on the root node but the output only picks up the values of the nodes.
<?xml version="1.0" encoding="utf-8"?>
<i:Root xmlns:i="http://www.somestuff.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance>
<i:Info>
<i:Num1>1234567890</i:Num1>
<i:Num2>1234567890</i:Num2>
<i:Service> code="1">String</i:Service>
<i:Type code="0">String</i:Type>
<i:Source>V</i:Source>
<i:MainNum>1234567890</i:MainNum>
<i:Name>a</i:Name>
<i:Code>a</i:Code>
<i:AttentionIndicator code="1">String</i:AttentionIndicator>
<i:SpecialMessage>a</i:SpecialMessage>
<i:AdditionalInfo>a</i:AdditionalInfo>
</i:Info>
</i:Root>
Output:
<?xml version="1.0" encoding="utf-8"?><i:Root xmlns:i="http://www.somestuff.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
1234567890
1234567890
String
String
V
1234567890
a
a
String
a
a
</i:Root>
This seems like I'm missing something pretty simple like the apply-templates not working the way I think. Thanks for the help!
I would like to get straight a copy of the input XML if the root node matches i:Root.
Then, a simple identity transform as in Kevin's answer will not help because the document is copied regardless of whether the outermost node is called i:Root
or not. Why? Because even if the template that matches /i:Root
is not invoked in this case, the other one is.
Use the xsl:copy-of
element to effectively copy everything, after checking the name of the document element.
Stylesheet
<xsl:stylesheet version="1.0" xmlns:i="http://www.somestuff.com"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:if test="self::i:Root">
<xsl:copy>
<xsl:copy-of select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Now, if we change the XML Input to:
<?xml version="1.0" encoding="utf-8"?>
<i:SomethingElse xmlns:i="http://www.somestuff.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<i:Info>
<i:Num1>1234567890</i:Num1>
<i:Num2>1234567890</i:Num2>
<i:Service> code="1">String</i:Service>
<i:Type code="0">String</i:Type>
<i:Source>V</i:Source>
<i:MainNum>1234567890</i:MainNum>
<i:Name>a</i:Name>
<i:Code>a</i:Code>
<i:AttentionIndicator code="1">String</i:AttentionIndicator>
<i:SpecialMessage>a</i:SpecialMessage>
<i:AdditionalInfo>a</i:AdditionalInfo>
</i:Info>
</i:SomethingElse>
We get the following output, as expected:
<?xml version="1.0" encoding="utf-8"?>
Otherwise (that is, if the document element is called i:Root
), the output XML is an exact copy of the input. Try different inputs online yourself, here .
Yes your missing something, but there is nothing wrong with your xsl:apply-template
or select for that matter.
You're missing a template for the other nodes besides i:Root, similar to this:
<xsl:stylesheet version="1.0" xmlns:i="http://www.somestuff.com" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/i:Root">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If you don't define a template, the xslt processor falls back to it's built-in templates.
The built-in template will for nodes:
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
Combined with the built-in template for text nodes:
<xsl:template match="text( )|@*">
<xsl:value-of select="."/>
</xsl:template>
... only your text is displayed.
Edit: just read your comment on getting a straight copy:
<xsl:stylesheet version="1.0" xmlns:i="http://www.somestuff.com" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/i:Root">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="/*" priority="-1">
<Empty/><!-- or sth creative, but valid xml should have a root node -->
</xsl:template>
</xsl:stylesheet>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.