C#中的XML过滤

时间:2012-01-10 14:13:41

标签: c# xml xslt

我有一个源XML文件。我为用户提供了一个UI,用于选择他们想要包含在结果XML中的元素。 UI的工作原理是加载XSD文件并在checkbox tree中显示元素。然后,用户可以检查他们需要的元素。

UI工作正常,但我需要一些关于后端逻辑的建议/指导:基本上我想要"应用过滤器"到源xml,但

  1. 我应该如何保存用户的选择(在分隔符中分隔值或??)和
  2. 我应该如何应用这个"过滤器" (也许是使用XSLT)?
  3. 修改 src xml结构如下所示:

    <IDs>
      <id1></id1>
      <id2></id2>
      ...
    </IDs>
    <Traveler>
      <name></name>
      <email></email>
      ...
    <Traveler>
    <Segments>
      <Segment i:type="Air">
        <carrier></carrier>
        ...
      </Segment>
      <Segment i:type="Hotel">
        <supplier></supplier>
        ...
      </Segment>
    </Segments>
    <Notes>
    ...
    </Notes>
    

    EDIT2:可以检查/取消选中所有这些元素以包含在生成的xml中。

3 个答案:

答案 0 :(得分:2)

如果您真的想使用XSLT执行此操作,请尝试此方法。它会复制您添加到第二个模板的任何XPath表达式都不匹配的所有元素和属性。你必须动态生成XSLT并编译它,所以它不会特别快:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="XPath for all non-selected elements"></xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

当我们创建一个用户友好的工具来处理我们的服务器配置文件(不是用户友好的XML)时,我们选择将用户选择(与默认配置的差异)直接存储为XSL转换

在您的情况下,这应该也可以,但它取决于XML的确切结构。如果您的原始XML类似于

<data>
  <item id="1">...</item>
  <item id="2">...</item>
  ...
</data>

您可以将选择存储为例如:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/data">
    <data>
        <xsl:apply-templates select="item" />
    </data>
    </xsl:template>

    <xsl:template match="item[@id='1']">
    <xsl:copy-of select="."/>
    </xsl:template>
    <xsl:template match="item[@id='3']">
    <xsl:copy-of select="."/>
    </xsl:template>
    <xsl:template match="item[@id='4']">
    <xsl:copy-of select="."/>
    </xsl:template>

    <xsl:template match="node()" />
</xsl:stylesheet>

这很简单,你的工具应该能够加载它并让用户修改他的选择。

答案 2 :(得分:1)

处理在很大程度上取决于您未显示的XML结构。

可以这么简单

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pWanted" select="'|A|C|'"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*/*">
   <xsl:if test="contains($pWanted, concat('|',name(), '|'))">
    <xsl:call-template name="identity"/>
   </xsl:if>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档

<t>
    <A>1</A>
    <B>2</B>
    <C>3</C>
</t>

生成了想要的正确结果(只有用户指定的元素AC保留在输出中):

<t>
   <A>1</A>
   <C>3</C>
</t>