求XSLT实现XML转换:跳过指定节点并保留结构与XML声明
问题
需要通过XSLT实现XML到XML的转换,具体需求:
- 转换后的输出需包含XML声明:
<?xml version='1.0' encoding='utf-8'?> - 跳过输入XML中
<G_1>节点下的<ORDER_NUM>135115</ORDER_NUM>元素 - 其余内容(包括结构层次)保持原样输出
现有XSLT输出不符合要求,缺失XML声明和外层结构,相关代码如下:
输入XML
<?xml version='1.0' encoding='utf-8'?> <!---------input xml ------------------------------------------> <DATA_DS> <G_1> <ORDER_NUM>135115</ORDER_NUM> <ACK_HEADER> <SENDER>9211111</SENDER> <RECEIVER>92511111</RECEIVER> <TRANSACTION_SET>CANCELED</TRANSACTION_SET> <ORDER_NUM>111115</ORDER_NUM> <ACK_LINE> <GL_COMPANY_ID>16881</GL_COMPANY_ID> <GL_DIVISION_ID>54880</GL_DIVISION_ID> <ITEM_DIVISION_ID>A</ITEM_DIVISION_ID> </ACK_LINE> <ACK_LINE> <GL_COMPANY_ID>161</GL_COMPANY_ID> <GL_DIVISION_ID>500</GL_DIVISION_ID> <ITEM_DIVISION_ID>G</ITEM_DIVISION_ID> </ACK_LINE> </ACK_HEADER> </G_1> </DATA_DS>
期望输出XML
<?xml version='1.0' encoding='utf-8'?> <!--Desired output --> <DATA_DS> <ACK_HEADER> <SENDER>9256510000</SENDER> <RECEIVER>9253070000</RECEIVER> <TRANSACTION_SET>CANCELED</TRANSACTION_SET> <ORDER_NUM>35115</ORDER_NUM> <ACK_LINE> <GL_COMPANY_ID>1601</GL_COMPANY_ID> <GL_DIVISION_ID>5400</GL_DIVISION_ID> <ITEM_DIVISION_ID>AG</ITEM_DIVISION_ID> </ACK_LINE> <ACK_LINE> <GL_COMPANY_ID>1601</GL_COMPANY_ID> <GL_DIVISION_ID>5400</GL_DIVISION_ID> <ITEM_DIVISION_ID>AG</ITEM_DIVISION_ID> </ACK_LINE> </ACK_HEADER> </DATA_DS>
尝试的XSLT
<?xml version='1.0' encoding='utf-8'?> <!--Tried with this xslt --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="utf-8" indent="yes"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="/"> <xsl:for-each select="DATA_DS"> <xsl:for-each select="G_1"> <xsl:for-each select="ACK_HEADER"> <xsl:element name="Sender"> <xsl:value-of select="SENDER"/> </xsl:element> <xsl:element name="RECEIVER"> <xsl:value-of select="RECEIVER"/> </xsl:element> <xsl:for-each select="ACK_LINE"> <SoHeader>Line start here</SoHeader> <xsl:element name="GL_COMPANY_ID"> <xsl:value-of select="GL_COMPANY_ID"/> </xsl:element> <xsl:element name="GL_DIVISION_ID"> <xsl:value-of select="GL_DIVISION_ID"/> </xsl:element> </xsl:for-each> <!-- ACK_LINE --> </xsl:for-each> <!-- ACK_HEADER --> </xsl:for-each> <!-- DATA_DS --> </xsl:for-each> </xsl:template> </xsl:stylesheet>
当前错误输出
<!--got this output --> <SENDER>9256510000</SENDER> <RECEIVER>9253070000</RECEIVER> <TRANSACTION_SET>CANCELED</TRANSACTION_SET> <PO_NUMBER>40X293825</PO_NUMBER> <PO_DATE>20220119</PO_DATE> <SO_NUMBER>35115</SO_NUMBER> <GL_COMPANY_ID>1601</GL_COMPANY_ID> <GL_DIVISION_ID>5400</GL_DIVISION_ID> <ITEM_DIVISION_ID>AG</ITEM_DIVISION_ID> <HEADER_ALLOWANCE_TYPE/>
正确XSLT方案
<?xml version='1.0' encoding='utf-8'?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 配置输出,确保包含XML声明、UTF-8编码及缩进 --> <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="no"/> <!-- 身份模板:默认复制所有节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 跳过G_1节点下值为135115的ORDER_NUM元素 --> <xsl:template match="G_1/ORDER_NUM[text()='135115']"/> <!-- 移除G_1外层标签,直接输出其子节点 --> <xsl:template match="G_1"> <xsl:apply-templates select="@*|node()"/> </xsl:template> </xsl:stylesheet>
方案说明
- XML声明保障:通过
<xsl:output>的omit-xml-declaration="no"参数,强制输出XML声明,同时指定编码和缩进格式。 - 默认内容保留:身份模板实现了所有节点和属性的默认复制,确保大部分内容原样输出。
- 精准跳过目标元素:通过匹配
G_1/ORDER_NUM[text()='135115'],用空模板直接跳过该节点的输出。 - 移除G_1标签:匹配
G_1节点时,仅输出其子节点,实现期望输出中去掉<G_1>外层标签的效果。
内容的提问来源于stack exchange,提问作者murali b
相关产品推荐
相关产品推荐

