XSLT: Remove Empty Nodes ~AND~ Nodes with Literal Value “Null”
All,
I have been using the extremely basic stylesheet at the very bottom of this post to remove empty element nodes from XML records. The XSLT does the job adequately, but the XML records actually include literal "null" values in some elements that the stylesheet doesn't remove. Example:
<marc:datafield tag="400" ind1="1" ind2=" ">
<marc:subfield code="a">null</marc:subfield>
<marc:subfield code="q">null</marc:subfield>
<marc:subfield code="d"></marc:subfield>
</marc:datafield>
I've been removing these "nulls" manually with a find and replace prior to running the XSLT, a procedure that works well enough--but it would be more sensible to have the XSLT itself remove these values as well as any empty nodes. In other words, I'd like to strip out nodes that contain "null"
<marc:subfield code="q">null</marc:subfield>
AND nodes like
<marc:subfield code="q"></marc:subfield>
so that the entire block of nodes represented in the top example in this message disappears entirely.
The XSLT immediately below succeeds in removing nodes with the literal "null" value, but it leaves the empty nodes in place. I need the XSLT to do both things simultaneously: remove literal "null" values and the nodes that contain them as well as the empty nodes. I've tried doing a "choose-otherwise" condition but it doesn't work.
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(node())]"/>
<xsl:template match="node()|@*">
<xsl:if test="(. != '') and (. != 'null')">
<xsl:copy>
<xsl:apply-templates select="node()[normalize-space()]|@*"/>
</xsl:copy>
</xsl:if>
</xsl:template>
Any assistance you might be able to offer would be hugely, immensely appreciated.
Regards, and many thanks--
Sed V.
ORIGINAL XSLT:
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(node())]"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()[normalize-space()]|@*"/>
</xsl:copy>
</xsl:template>
xslt
add a comment |
All,
I have been using the extremely basic stylesheet at the very bottom of this post to remove empty element nodes from XML records. The XSLT does the job adequately, but the XML records actually include literal "null" values in some elements that the stylesheet doesn't remove. Example:
<marc:datafield tag="400" ind1="1" ind2=" ">
<marc:subfield code="a">null</marc:subfield>
<marc:subfield code="q">null</marc:subfield>
<marc:subfield code="d"></marc:subfield>
</marc:datafield>
I've been removing these "nulls" manually with a find and replace prior to running the XSLT, a procedure that works well enough--but it would be more sensible to have the XSLT itself remove these values as well as any empty nodes. In other words, I'd like to strip out nodes that contain "null"
<marc:subfield code="q">null</marc:subfield>
AND nodes like
<marc:subfield code="q"></marc:subfield>
so that the entire block of nodes represented in the top example in this message disappears entirely.
The XSLT immediately below succeeds in removing nodes with the literal "null" value, but it leaves the empty nodes in place. I need the XSLT to do both things simultaneously: remove literal "null" values and the nodes that contain them as well as the empty nodes. I've tried doing a "choose-otherwise" condition but it doesn't work.
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(node())]"/>
<xsl:template match="node()|@*">
<xsl:if test="(. != '') and (. != 'null')">
<xsl:copy>
<xsl:apply-templates select="node()[normalize-space()]|@*"/>
</xsl:copy>
</xsl:if>
</xsl:template>
Any assistance you might be able to offer would be hugely, immensely appreciated.
Regards, and many thanks--
Sed V.
ORIGINAL XSLT:
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(node())]"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()[normalize-space()]|@*"/>
</xsl:copy>
</xsl:template>
xslt
add a comment |
All,
I have been using the extremely basic stylesheet at the very bottom of this post to remove empty element nodes from XML records. The XSLT does the job adequately, but the XML records actually include literal "null" values in some elements that the stylesheet doesn't remove. Example:
<marc:datafield tag="400" ind1="1" ind2=" ">
<marc:subfield code="a">null</marc:subfield>
<marc:subfield code="q">null</marc:subfield>
<marc:subfield code="d"></marc:subfield>
</marc:datafield>
I've been removing these "nulls" manually with a find and replace prior to running the XSLT, a procedure that works well enough--but it would be more sensible to have the XSLT itself remove these values as well as any empty nodes. In other words, I'd like to strip out nodes that contain "null"
<marc:subfield code="q">null</marc:subfield>
AND nodes like
<marc:subfield code="q"></marc:subfield>
so that the entire block of nodes represented in the top example in this message disappears entirely.
The XSLT immediately below succeeds in removing nodes with the literal "null" value, but it leaves the empty nodes in place. I need the XSLT to do both things simultaneously: remove literal "null" values and the nodes that contain them as well as the empty nodes. I've tried doing a "choose-otherwise" condition but it doesn't work.
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(node())]"/>
<xsl:template match="node()|@*">
<xsl:if test="(. != '') and (. != 'null')">
<xsl:copy>
<xsl:apply-templates select="node()[normalize-space()]|@*"/>
</xsl:copy>
</xsl:if>
</xsl:template>
Any assistance you might be able to offer would be hugely, immensely appreciated.
Regards, and many thanks--
Sed V.
ORIGINAL XSLT:
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(node())]"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()[normalize-space()]|@*"/>
</xsl:copy>
</xsl:template>
xslt
All,
I have been using the extremely basic stylesheet at the very bottom of this post to remove empty element nodes from XML records. The XSLT does the job adequately, but the XML records actually include literal "null" values in some elements that the stylesheet doesn't remove. Example:
<marc:datafield tag="400" ind1="1" ind2=" ">
<marc:subfield code="a">null</marc:subfield>
<marc:subfield code="q">null</marc:subfield>
<marc:subfield code="d"></marc:subfield>
</marc:datafield>
I've been removing these "nulls" manually with a find and replace prior to running the XSLT, a procedure that works well enough--but it would be more sensible to have the XSLT itself remove these values as well as any empty nodes. In other words, I'd like to strip out nodes that contain "null"
<marc:subfield code="q">null</marc:subfield>
AND nodes like
<marc:subfield code="q"></marc:subfield>
so that the entire block of nodes represented in the top example in this message disappears entirely.
The XSLT immediately below succeeds in removing nodes with the literal "null" value, but it leaves the empty nodes in place. I need the XSLT to do both things simultaneously: remove literal "null" values and the nodes that contain them as well as the empty nodes. I've tried doing a "choose-otherwise" condition but it doesn't work.
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(node())]"/>
<xsl:template match="node()|@*">
<xsl:if test="(. != '') and (. != 'null')">
<xsl:copy>
<xsl:apply-templates select="node()[normalize-space()]|@*"/>
</xsl:copy>
</xsl:if>
</xsl:template>
Any assistance you might be able to offer would be hugely, immensely appreciated.
Regards, and many thanks--
Sed V.
ORIGINAL XSLT:
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(node())]"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()[normalize-space()]|@*"/>
</xsl:copy>
</xsl:template>
xslt
xslt
edited Nov 20 '18 at 18:49
pushkin
4,050112752
4,050112752
asked Nov 20 '18 at 18:43
Sediziose_VociSediziose_Voci
61
61
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You're almost there. Your template
<xsl:template match="*[not(node())]"/>
filters empty elements - just add or text() = 'null'
to the predicate to filter elements that wrap literal null
strings.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<!-- Identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Filter empty elements or elements that contain the text 'null' -->
<xsl:template match="*[not(node()) or text() = 'null']"/>
</xsl:stylesheet>
Thank you, thank you. This is extremely helpful. The formula below is what ended up doing what I needed. It includes the crucial, indispensable piece you supplied.
– Sediziose_Voci
Nov 20 '18 at 23:09
<xsl:stylesheet version="2.0" xmlns:xsl="w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/> <xsl:strip-space elements=""/> <xsl:template match="*[not(node())]"/> <xsl:template match="node()|@"> <xsl:copy> <xsl:apply-templates select="node()[normalize-space()]|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(node()) or text() = 'null']"/> </xsl:stylesheet>
– Sediziose_Voci
Nov 20 '18 at 23:12
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399519%2fxslt-remove-empty-nodes-and-nodes-with-literal-value-null%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You're almost there. Your template
<xsl:template match="*[not(node())]"/>
filters empty elements - just add or text() = 'null'
to the predicate to filter elements that wrap literal null
strings.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<!-- Identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Filter empty elements or elements that contain the text 'null' -->
<xsl:template match="*[not(node()) or text() = 'null']"/>
</xsl:stylesheet>
Thank you, thank you. This is extremely helpful. The formula below is what ended up doing what I needed. It includes the crucial, indispensable piece you supplied.
– Sediziose_Voci
Nov 20 '18 at 23:09
<xsl:stylesheet version="2.0" xmlns:xsl="w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/> <xsl:strip-space elements=""/> <xsl:template match="*[not(node())]"/> <xsl:template match="node()|@"> <xsl:copy> <xsl:apply-templates select="node()[normalize-space()]|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(node()) or text() = 'null']"/> </xsl:stylesheet>
– Sediziose_Voci
Nov 20 '18 at 23:12
add a comment |
You're almost there. Your template
<xsl:template match="*[not(node())]"/>
filters empty elements - just add or text() = 'null'
to the predicate to filter elements that wrap literal null
strings.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<!-- Identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Filter empty elements or elements that contain the text 'null' -->
<xsl:template match="*[not(node()) or text() = 'null']"/>
</xsl:stylesheet>
Thank you, thank you. This is extremely helpful. The formula below is what ended up doing what I needed. It includes the crucial, indispensable piece you supplied.
– Sediziose_Voci
Nov 20 '18 at 23:09
<xsl:stylesheet version="2.0" xmlns:xsl="w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/> <xsl:strip-space elements=""/> <xsl:template match="*[not(node())]"/> <xsl:template match="node()|@"> <xsl:copy> <xsl:apply-templates select="node()[normalize-space()]|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(node()) or text() = 'null']"/> </xsl:stylesheet>
– Sediziose_Voci
Nov 20 '18 at 23:12
add a comment |
You're almost there. Your template
<xsl:template match="*[not(node())]"/>
filters empty elements - just add or text() = 'null'
to the predicate to filter elements that wrap literal null
strings.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<!-- Identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Filter empty elements or elements that contain the text 'null' -->
<xsl:template match="*[not(node()) or text() = 'null']"/>
</xsl:stylesheet>
You're almost there. Your template
<xsl:template match="*[not(node())]"/>
filters empty elements - just add or text() = 'null'
to the predicate to filter elements that wrap literal null
strings.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<!-- Identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Filter empty elements or elements that contain the text 'null' -->
<xsl:template match="*[not(node()) or text() = 'null']"/>
</xsl:stylesheet>
answered Nov 20 '18 at 19:19
teppicteppic
5,30411826
5,30411826
Thank you, thank you. This is extremely helpful. The formula below is what ended up doing what I needed. It includes the crucial, indispensable piece you supplied.
– Sediziose_Voci
Nov 20 '18 at 23:09
<xsl:stylesheet version="2.0" xmlns:xsl="w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/> <xsl:strip-space elements=""/> <xsl:template match="*[not(node())]"/> <xsl:template match="node()|@"> <xsl:copy> <xsl:apply-templates select="node()[normalize-space()]|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(node()) or text() = 'null']"/> </xsl:stylesheet>
– Sediziose_Voci
Nov 20 '18 at 23:12
add a comment |
Thank you, thank you. This is extremely helpful. The formula below is what ended up doing what I needed. It includes the crucial, indispensable piece you supplied.
– Sediziose_Voci
Nov 20 '18 at 23:09
<xsl:stylesheet version="2.0" xmlns:xsl="w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/> <xsl:strip-space elements=""/> <xsl:template match="*[not(node())]"/> <xsl:template match="node()|@"> <xsl:copy> <xsl:apply-templates select="node()[normalize-space()]|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(node()) or text() = 'null']"/> </xsl:stylesheet>
– Sediziose_Voci
Nov 20 '18 at 23:12
Thank you, thank you. This is extremely helpful. The formula below is what ended up doing what I needed. It includes the crucial, indispensable piece you supplied.
– Sediziose_Voci
Nov 20 '18 at 23:09
Thank you, thank you. This is extremely helpful. The formula below is what ended up doing what I needed. It includes the crucial, indispensable piece you supplied.
– Sediziose_Voci
Nov 20 '18 at 23:09
<xsl:stylesheet version="2.0" xmlns:xsl="w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/> <xsl:strip-space elements=""/> <xsl:template match="*[not(node())]"/> <xsl:template match="node()|@"> <xsl:copy> <xsl:apply-templates select="node()[normalize-space()]|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(node()) or text() = 'null']"/> </xsl:stylesheet>
– Sediziose_Voci
Nov 20 '18 at 23:12
<xsl:stylesheet version="2.0" xmlns:xsl="w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/> <xsl:strip-space elements=""/> <xsl:template match="*[not(node())]"/> <xsl:template match="node()|@"> <xsl:copy> <xsl:apply-templates select="node()[normalize-space()]|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(node()) or text() = 'null']"/> </xsl:stylesheet>
– Sediziose_Voci
Nov 20 '18 at 23:12
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399519%2fxslt-remove-empty-nodes-and-nodes-with-literal-value-null%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown