gpt4 book ai didi

xslt - 复制 XML,同时排除父节点,删除特定子节点,并覆盖部分子节点

转载 作者:行者123 更新时间:2023-12-01 03:41:05 26 4
gpt4 key购买 nike

我已经查看了几篇分别做这些事情的帖子,但还没有成功地将它们组合在一起。

我有一个类似于这个结构的输入:

 <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 中的任何 null children

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) 如果我想更新一个不为空的子节点的值,我会这样做吗?有一个额外的要求来更新一些子节点,所以我还在考虑如何做,这似乎是正确的方法,但我想验证一下。

 <xsl:template match='childNodeA'>
<childNodeA>
<xsl:value-of select='someValue/>
</childNodeA>
</xsl:template>

如果不清楚,我深表歉意,但请随时索取您需要的任何更多详细信息,并在此先感谢您提供的任何帮助。

最佳答案

您发布的输出 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>

关于xslt - 复制 XML,同时排除父节点,删除特定子节点,并覆盖部分子节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14929804/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com