我已经回顾了几个分别完成这些事情的帖子,但还没有成功地将它们组合在一起。
我有类似于这种结构的输入:
<Response>
<Confirmation>Success</Confirmation>
<SecondResponse>
<InquiryResponse>
<ID>99999</ID>
<Confirmation>Success</Confirmation>
<Exception/>
<!-- The following structure repeats a varying amount of times -->
<DataNode1>
<!-- Child nodes could be null, transform should remove null nodes -->
<Child1>data</Child1>
...
<Childn>dataN</Childn>
</DataNode1>
...
<DataNodeN>
<Child1>data</Child1>
...
<Childn>dataN</Childn>
</DataNodeN>
</InquiryResponse>
</SecondResponse>
</Response>
现在,我需要完成以下事项:
1)复制<InquiryResponse>
(但不是<InquiryResponse>
本身)的所有子节点
2)排除<Confirmation>
和<Exception>
节点
3)排除DataNode中的所有空子项
4)在DataNode中插入一个新的子元素
所以期望的输出看起来像这样:
<ID>99999</ID>
<DataNode1>
<Child1>data</Child1>
<ChiildInsert>newData</ChildInsert>
<Childn>dataN</Childn>
</DataNode1>
...
<DataNodeN>
<Child1>data</Child1>
<ChildInsert>newData</ChildInsert>
<Childn>dataN</Childn>
</DataNodeN>
我相信我必须通过为每个DataNode创建一个模板(我知道可能发生的所有可能值),以及删除我不想要的节点的模板,然后将它们全部应用到主副本模板忽略空节点。这是我目前使用2.0的XSLT版本 - 虽然我知道它并不完全完整,但就我而言:
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Remove Unwanted Nodes -->
<xsl:template match='Confirmation|Exception'/>
<!-- DataNode Template -->
<template match='DataNode1'>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<ChildInsert>
<xsl:value-of select='newData'/>
</ChildInsert>
</xsl:copy>
</xsl:template>
<!-- Identity Transform -->
<xsl:template match='@*|node()'>
<xsl:if test='. != ""'>
<xsl:copy>
<xsl:apply-templates select='@*|node()'/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
这是我使用Saxon-PE 9.3.0.5生成的输出
<Response>
<SecondResponse>
<InquiryResponse>
<ID>99999</ID>
<DataNode1>
<Child1>data</Child1>
<ChiildInsert>newData</ChildInsert>
<Childn>dataN</Childn>
</DataNode1>
....
<DataNodeN>...</DataNodeN>
</InquiryResponse>
</SecondResponse>
</Response>
显然,我还没有得到所有的回复家长,因为我没有指定处理它们的方法;但是,每当我尝试将模板与XPath匹配时,我都会得到数据,而不是XML。我知道我可以通过另一个只复制<InquiryResponse>
的子节点的转换来传递它,但我觉得应该有更优雅的方式来代替它。以下是我仍然面临的问题/问题。
1)由于使用这样的模板:<xsl:template match='Response'/>
会使我的整个响应无效,我尝试将标识模板切换为匹配Response/SecondResponse/InquiryResponse/*
,但结果只生成文本数据,而不是XML。
2)当<Exception>
节点填充了一个值时,它会继续被复制而不是像<Confirmation>
节点一样被删除。
3)如果我想更新非null的子节点的值,我会这样做吗?还有一个额外的要求是更新一些子节点,所以我仍在考虑如何做,这似乎是正确的方法,但我想验证。
<xsl:template match='childNodeA'>
<childNodeA>
<xsl:value-of select='someValue/>
</childNodeA>
</xsl:template>
如果不清楚我会道歉,但随时可以请求您提供的任何进一步细节,并提前感谢任何可以提供帮助的人。
答案 0 :(得分:8)
您发布的输出XML格式不正确,因为它没有根元素,但是这个XSLT 1.0样式表应该按照您的意愿执行:
<强>样式表强>:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:strip-space elements="*"/>
<!-- Identity transform -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- Apply all child nodes; don't copy the element itself -->
<xsl:template match="Response | SecondResponse | InquiryResponse">
<xsl:apply-templates/>
</xsl:template>
<!-- Drop elements -->
<xsl:template match="Confirmation | Exception"/>
<xsl:template match="DataNode1 | DataNode2 | DataNodeN">
<xsl:copy>
<!-- Apply Child1, ignore children with no text content -->
<xsl:apply-templates select="Child1[normalize-space(.)]"/>
<!-- Insert new element -->
<ChildInsert>newData</ChildInsert>
<!-- Apply all other child elements except Child1 -->
<xsl:apply-templates select="*[normalize-space(.)][not(self::Child1)]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<强>输入强>:
<Response>
<Confirmation>Success</Confirmation>
<SecondResponse>
<InquiryResponse>
<ID>99999</ID>
<Confirmation>Success</Confirmation>
<Exception/>
<!-- The following structure repeats a varying amount of times -->
<DataNode1>
<!-- Child nodes could be null, transform should remove null nodes -->
<Child1>data</Child1>
<Childn>dataN</Childn>
</DataNode1>
<DataNodeN>
<Child1>data</Child1>
<Childn>dataN</Childn>
</DataNodeN>
</InquiryResponse>
</SecondResponse>
</Response>
<强>输出强>:
<?xml version="1.0" encoding="utf-8"?>
<ID>99999</ID>
<DataNode1>
<Child1>data</Child1>
<ChildInsert>newData</ChildInsert>
<Childn>dataN</Childn>
</DataNode1>
<DataNodeN>
<Child1>data</Child1>
<ChildInsert>newData</ChildInsert>
<Childn>dataN</Childn>
</DataNodeN>
请注意,由于您没有指定“null”的含义,我认为它是指没有文本内容的元素。所以上面的代码会丢弃一个<Child1>
元素,如下所示:
<Child1>
<GrandChild1/>
</Child1>