c# - 使用 XSLT 从 XML 中查询和提取数据
问题描述
我正在尝试使用 XSLT 解决以下问题,但有点卡住了。
我有一个工具的 ID,比如说一把锤子。我需要获取该 ID 变量,将其传递给 XSLT 样式表,使用 XSLT 匹配包含具有该 ID 的工具的 XML 文件中的所有 Task 元素。
所以在一个文档(tasks.xml)中我有以下内容(注意<tool><id>
)
<data>
<DMs>
<task>
<DMC>TEST-4BX-AG3-00-00-0000-125B-A</DMC>
<techName>Fixing fence</techName>
<infoName>Inserting panels</infoName>
<tools>
<tool>
<id>1</id><qty>1</qty>
</tool>
<tool>
<id>4</id><qty>1</qty>
</tool>
</tools>
</task>
<task>
<DMC>TEST-4BX-AG3-00-00-0000-125B-A</DMC>
<techName>Fixing floor</techName>
<infoName>Install floorboard</infoName>
<notes>-</notes>
<tools>
<tool>
<id>89</id><qty>1</qty>
</tool>
<tool>
<id>25</id><qty>2</qty>
</tool>
</tools>
</task>
</DMs>
</data>
所以假设锤子的 ID 是“1”,我现在需要搜索 Tasks.xml 文件并匹配使用锤子的所有任务。只有具有锤子的任务才应包含在输出中。
这是问题的第一部分。
我还有一个文件Tools.xml,里面包含了所有的工具信息,如下:
<data>
<tools>
<tool id="1">
<toolName>Hammer</toolName>
<toolPN>345123</toolPN>
<toolCage>-</toolCage>
</tool>
<tool id="2">
<toolName>Digital Multimeter Set</toolName>
<toolPN>Fluke Model No. 89IV</toolPN>
<toolCage>-</toolCage>
</tool>
<tool id="3">
<toolName>Digital Storage Oscilloscope</toolName>
<toolPN>Tektronix 3052B</toolPN>
<toolCage>-</toolCage>
</tool>
<tool id="4">
<toolName>Socket set</toolName>
<toolPN>737828</toolPN>
<toolCage>-</toolCage>
</tool>
</tools>
</data>
我还需要从 Tools.XML 中提取工具的实际名称和详细信息,以便输出 xml 文件列出工具详细信息,例如名称和部件号等,而不仅仅是一个 ID。
所以我想要的是这样的输出:
<data>
<DMs>
<task>
<DMC>TEST-4BX-AG3-00-00-0000-125B-A</DMC>
<techName>Fixing fence</techName>
<infoName>Inserting panels</infoName>
<tools>
<tool id="1">
<toolName>Hammer</toolName>
<toolPN>345123</toolPN>
<toolCage>-</toolCage>
</tool>
<tool id="4">
<toolName>Socket set</toolName>
<toolPN>737828</toolPN>
<toolCage>-</toolCage>
</tool>
</tools>
</task>
<task>
我一直在搞乱 XSLT,但无法做到正确。我尝试的一切似乎都从输出中完全删除了工具。
这是我一直在使用 Document() 函数和 XSLT Key 玩过的一些 XSLT,但我真的只是在尝试学习 XSLT 并且感到沮丧。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="dataModuleLookupDoc" select="document('C:\TOOLS.xml')"/>
<xsl:key name="toolIDKey" match="tool" use="@id"/>
<xsl:template match="task">
<xsl:apply-templates select="$dataModuleLookupDoc"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="tools"/>
<xsl:template match="tool">
<xsl:variable name="toolID" select="@ID"/>
<xsl:for-each select="$dataModuleLookupDoc">
<xsl:value-of select="key('toolIDKey',toolID)"/>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:apply-templates/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
解决方案
尝试xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME1 = @"c:\temp\test1.xml";
const string FILENAME2 = @"c:\temp\test2.xml";
static void Main(string[] args)
{
XDocument xTools = XDocument.Load(FILENAME2);
Dictionary<int, Tool> toolsDict = xTools.Descendants("tool")
.Select(x => new Tool() {
id = (int)x.Attribute("id"),
name = (string)x.Element("toolName"),
pn = (string)x.Element("toolPN"),
cage = (string)x.Element("toolCage")
}).GroupBy(x => x.id, y => y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
XDocument xTasks = XDocument.Load(FILENAME1);
List<XElement> toolTask = xTasks.Descendants("tool").ToList();
foreach (XElement tool in toolTask)
{
int id = (int)tool.Element("id");
int qty = (int)tool.Element("qty");
if(toolsDict.ContainsKey(id))
{
Tool idTool = toolsDict[id];
tool.ReplaceWith(new XElement("tool", new object[] {
new XAttribute("id", id),
new XAttribute("qty", qty),
new XElement("toolName", idTool.name),
new XElement("toolPN", idTool.pn),
new XElement("toolCage", idTool.cage)
}));
}
// <toolName>Hammer</toolName>
// <toolPN>345123</toolPN>
// <toolCage>-</toolCage>
//</tool>
}
}
}
public class Tool
{
public int id { get;set;}
public string name { get; set; }
public string pn { get; set; }
public string cage { get; set; }
}
}
推荐阅读
- html - 我对相邻的 2 个 div 有问题
- html - 如何优化此代码以用于电子邮件签名?
- python-3.x - Python 版本和 BQ API 兼容性
- excel - 从函数调用时 Excel 宏不起作用
- bash - 带有 bash gcloud 身份令牌、heredoc 和 printf 的 kubectl 补丁秘密
- php - Laravel 时间戳记录谁做了某些动作(比如 created_at & created_by, updated_at & updated_by)
- java - 在 android (Java 8) 上运行 TensorFlow Lite 时出现 java.lang.NoSuchMethodError
- laravel - 在 Laravel 中存储每条记录的图像的方法?
- django - 使用 vue-recaptcha 和 Django Rest Framework 中间件的 CSRF 令牌丢失错误
- python - 如果不是现有值,则合并应采用 Nan 值