非常难以将解释纳入准确的标题,但我尝试过。
无论如何这个问题很简单。
给出以下xml:
<Parent>
<Child/>
<Child/>
<Child/>
<Child/>
<!-- Trying to insert an element here -->
<OtherChild/>
<OtherChild/>
<OtherChild/>
</Parent>
并假设如下:
我的解决方案:
结果:
一个。如果我们试图插入的元素存在,我们插入后。
B.如果存在先前的兄弟姐妹,我们之后插入
C.如果不存在先前的兄弟姐妹,但是父母我们是否在父母之前
D.从那里向上走树,我们将继续前往当前父节点的下一个父节点或前一节节点,直到我们找到一个存在的节点,然后将整个树插入到我们试图插入的元素中。
我目前正在C#代码中执行此操作,首先使用模式发现前面的兄弟,然后迭代地尝试选择一个,直到我找到一个或到达列表的末尾。然后我尝试发现父母然后重复父母作为要插入的元素。
问题:
是否有可能以另一种更快,更有效,更整洁,更好的方式做到这一点?
我刚学习XSLT,是否可以使用完美的转换(注意必须是XSLT 1.0)。
另外,聪明的方法可以最大限度地减少目前的工作,它基本上必须遍历整个树,直到它到达一个可能需要大量工作的现有节点。
注意:作为参考,这实际上是在InfoPath中使用,我将在其中处理主数据源。特别是我指的是重复表,用户可以从表中删除所有行,此时任何试图向该表添加行的代码都可能非常困难。
InfoPath本身能够像饼一样简单地向表中添加新行,如果我能弄清楚它们如何管理它会很棒。取而代之的是,我很高兴只是有一个简单的方法来做到这一点。
我已经找到了问题的解决方案,正如我所说,我只是在寻找一些人来反省意见,看看我是否能得到一些改进。我感谢您提出的任何建议。
谢谢:)
答案 0 :(得分:0)
这不是一个完整的答案,但如果你给我一些澄清,我可能会解决一些问题。
以下给出了xml:
<root>
<parent>
<child>child1</child>
<child>child2</child>
<otherChild>other1</otherChild>
</parent>
</root>
将其转换为:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<parent>
<child>child1</child>
<child>child2</child>
<insertedChild>inserted1</insertedChild>
<otherChild>other2</otherChild>
</parent>
</root>
这是xsl:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/root">
<xsl:for-each select=".">
<xsl:element name="root">
<xsl:for-each select="parent">
<xsl:element name="parent">
<xsl:copy-of select="child" />
<xsl:element name="insertedChild">
inserted1
</xsl:element>
<xsl:copy-of select="otherChild" />
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
对于我们希望添加的元素之前和之后的任意数量的不同元素,可以对其进行更改。
我从问题描述中得不到的是要添加的元素是否可以在任何地方;也就是说,我们事先并不知道我们希望结束的确切模式。
这是一个需要为多个元素运行的转换吗?如果是这种情况,您可能需要创建多个xsl文件或将其包含在此文件中。无论哪种方式,它都会有点复杂。
然而,XSL对参数化是开放的,因为您可以选择插入元素的名称和值,例如:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="insertedChild"></xsl:param>
<xsl:param name="valueOfInsertedChild"></xsl:param>
<xsl:template match="/root">
<xsl:for-each select=".">
<xsl:element name="root">
<xsl:for-each select="parent">
<xsl:element name="parent">
<xsl:copy-of select="child" />
<xsl:element name="{$insertedChild}">
<xsl:value-of select="$valueOfInsertedChild" />
</xsl:element>
<xsl:copy-of select="otherChild" />
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我希望这甚至有点接近你想要的东西。澄清上面提到的要点,我们可能会做得更好。
答案 1 :(得分:0)
好的,我相信我得到了这个。声明是4个参数,定义插入元素的名称,值,一个参数定义哪个是前一个元素,一个定义父元素。
两个限制:
您无法获得混合内容(即插入节点) 另一个有字符数据而不是其他节点。)
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="insertedChild">a</xsl:param>
<xsl:param name="valueOfInsertedChild">a</xsl:param>
<xsl:param name="appendAfterChild">child</xsl:param>
<xsl:param name="appendIntoNode">parent</xsl:param>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:choose>
<xsl:when test="name() = $appendIntoNode">
<xsl:call-template name="insertNode" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="recurse" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="recurse">
<xsl:copy>
<xsl:for-each select="child::node()">
<xsl:choose>
<xsl:when test="name() = $appendIntoNode">
<xsl:call-template name="insertNode" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="recurse" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template name="insertNode">
<xsl:element name="{name()}">
<xsl:for-each select="*[(following-sibling::*[name()=$appendAfterChild] and name()!=$appendAfterChild) or name()=$appendAfterChild]">
<xsl:copy-of select="." />
</xsl:for-each>
<xsl:element name="{$insertedChild}">
<xsl:value-of select="$valueOfInsertedChild" />
</xsl:element>
<xsl:for-each select="*[not((following-sibling::*[name()=$appendAfterChild] and name()!=$appendAfterChild) or name()=$appendAfterChild)]">
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
由于性能原因,我不确定它是如何工作的,但你可以尝试一下。我认为这与你的要求非常接近。让我知道这是怎么回事。 :)