xml - XSLT 1.0 - 基于来自不同节点的属性值创建节点
问题描述
我很难处理以下用例。
这是 XML:
<NodeA>
<NodeB>
<Application id="I-555" name="Text1" XorY="Y" />
<Application id="I-666" name="Text2" XorY="X" />
<Application id="I-777" name="Text3" XorY="Y" />
<Application id="I-888" name="Text4" XorY="X" />
</NodeB>
</NodeA>
<NodeD>
<NodeE>
<Process id="111" name="Text1" />
<Process id="222" name="Text2" />
<Process id="333" name="Text2" />
<Process id="444" name="Text2" />
</NodeE>
</NodeD>
<Links_between_Process_and_Application>
<Link_Process_App app_id="I-555" process_id="111" />
<Link_Process_App app_id="I-666" process_id="222" />
<Link_Process_App app_id="I-777" process_id="333" />
<Link_Process_App app_id="I-888" process_id="444" />
</Links_between_Process_and_Application>
我想要实现的是创建/转换具有两个新链接的新 XML,在节点“Application”和“Process”之间,基于 node <Links_between_Process_and_Application>
。
棘手的部分是(至少对我而言)是根据XorY
(伪代码)的属性值创建两个不同的链接/节点:
通过 IF 遍历(for-each)时<Links_between_Process_and_Application>
(检查当前 app_id(例如 I-555)如果节点“Application”中的@XorY=' X ')创建 < Link_Process_Application > ELSE IF(检查当前 app_id(例如 I -555) 如果@XorY=' Y ' 在节点“应用程序”中)创建< Link_Process_IDP >
我已经为转换编写了两个 XSLT 并生成了这两个链接(没有检查属性 XorY),因为我真的不知道如何从不同的用例中检查属性的值:
<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<ImportSchemaBase>
<xsl:for-each select="Links_between_Process_and_Application/Link_Process_App">
<Link_Process_Application>
<SourceKey>
<xsl:value-of select="@process_id"/>
</SourceKey>
<TargetKey>
<xsl:value-of select="@app_id"/>
</TargetKey>
</Link_Process_Application>
</xsl:for-each>
</ImportSchemaBase>
</xsl:template>
</xsl:stylesheet>
和:
<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<ImportSchemaBase>
<xsl:for-each select="Links_between_Process_and_Application/Link_Process_App">
<Link_Process_IDP>
<SourceKey>
<xsl:value-of select="@process_id"/>
</SourceKey>
<TargetKey>
<xsl:value-of select="@app_id"/>
</TargetKey>
</Link_Process_IDP>
</xsl:for-each>
</ImportSchemaBase>
</xsl:template>
</xsl:stylesheet>
结果应该是:
创建 Link_Process_IDP 因为对于“app_id=I-555” XorY 是 Y
<Link_Process_IDP>
<SourceKey>111</SourceKey>
<TargetKey>I-555</TargetKey>
</Link_Process_IDP>
创建 Link_Process_Application 因为对于“app_id=I-666” XorY 是 X
<Link_Process_Application>
<SourceKey>222</SourceKey>
<TargetKey>I-666</TargetKey>
</Link_Process_Application>
创建 Link_Process_IDP,因为对于“app_id=I-777”,XorY 是 Y
<Link_Process_IDP>
<SourceKey>333</SourceKey>
<TargetKey>I-777</TargetKey>
</Link_Process_IDP>
创建 Link_Process_Application 因为对于“app_id=I-888” XorY 是 X
<Link_Process_Application>
<SourceKey>444</SourceKey>
<TargetKey>I-888</TargetKey>
</Link_Process_Application>
非常感谢你,很抱歉描述太长了!
解决方案
您的输入不是 XML - 它缺少单个根元素(您的预期输出也是如此)。
给定格式良好的 XML 输入,使用key很容易完成任务:
XML
<root>
<NodeA>
<NodeB>
<Application id="I-555" name="Text1" XorY="Y" />
<Application id="I-666" name="Text2" XorY="X" />
<Application id="I-777" name="Text3" XorY="Y" />
<Application id="I-888" name="Text4" XorY="X" />
</NodeB>
</NodeA>
<NodeD>
<NodeE>
<Process id="111" name="Text1" />
<Process id="222" name="Text2" />
<Process id="333" name="Text2" />
<Process id="444" name="Text2" />
</NodeE>
</NodeD>
<Links_between_Process_and_Application>
<Link_Process_App app_id="I-555" process_id="111" />
<Link_Process_App app_id="I-666" process_id="222" />
<Link_Process_App app_id="I-777" process_id="333" />
<Link_Process_App app_id="I-888" process_id="444" />
</Links_between_Process_and_Application>
</root>
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="app" match="Application" use="@id" />
<xsl:template match="/root">
<output>
<xsl:for-each select="Links_between_Process_and_Application/Link_Process_App">
<xsl:variable name="xory" select="key('app', @app_id)/@XorY" />
<xsl:variable name="name">
<xsl:choose>
<xsl:when test="$xory = 'X'">Link_Process_Application</xsl:when>
<xsl:when test="$xory = 'Y'">Link_Process_IDP</xsl:when>
<xsl:otherwise>SomethingElse</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{$name}">
<SourceKey>
<xsl:value-of select="@process_id"/>
</SourceKey>
<TargetKey>
<xsl:value-of select="@app_id"/>
</TargetKey>
</xsl:element>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
结果
<?xml version="1.0" encoding="UTF-8"?>
<output>
<Link_Process_IDP>
<SourceKey>111</SourceKey>
<TargetKey>I-555</TargetKey>
</Link_Process_IDP>
<Link_Process_Application>
<SourceKey>222</SourceKey>
<TargetKey>I-666</TargetKey>
</Link_Process_Application>
<Link_Process_IDP>
<SourceKey>333</SourceKey>
<TargetKey>I-777</TargetKey>
</Link_Process_IDP>
<Link_Process_Application>
<SourceKey>444</SourceKey>
<TargetKey>I-888</TargetKey>
</Link_Process_Application>
</output>
请注意,如果X
和Y
是互斥的,您可以将其进一步缩短为:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="app" match="Application" use="@id" />
<xsl:template match="/root">
<output>
<xsl:for-each select="Links_between_Process_and_Application/Link_Process_App">
<xsl:variable name="name">
<xsl:choose>
<xsl:when test="key('app', @app_id)/@XorY = 'X'">Link_Process_Application</xsl:when>
<xsl:otherwise>Link_Process_IDP</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{$name}">
<SourceKey>
<xsl:value-of select="@process_id"/>
</SourceKey>
<TargetKey>
<xsl:value-of select="@app_id"/>
</TargetKey>
</xsl:element>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
推荐阅读
- performance - 未处理的异常如何导致 Azure 应用服务缓慢?
- java - 在Java 8中通过流将列表转换为具有父子关系的嵌套列表
- angular - 如何将配置参数传递给角度库?
- mongodb - 如何在mongodb的条件语句中使用元素匹配?
- python - 如何去除重叠轮廓并将每个字符分离为单独的轮廓以进行字符提取?
- webrtc - ICE vs STUN vs TURN
- python - dict() 函数改变列表中元素的顺序
- docker - 如何在 docker compose 中引用环境变量作为卷创建的一部分
- javascript - 我的视频不能仅在移动设备上自动播放,我的代码有什么问题?
- node.js - 即使对于新/小型项目,Angular8,Ng serve 在我的机器上也很慢