非常有趣的 Python bounty question我知道这可以用 XSLT 1.0 解决。请注意,这不是一个重复的问题,因为之前的帖子以 Python 方法为中心,而这是尝试对同一问题使用 XSLT 解决方案。以下是我的尝试,但仅限于预设数量的父/子组合,这里有四个级别深,并且有条件地遍历每个级别。
有没有办法将我的解决方案概括为任何组合级别?我知道这可能需要使用 --> 分隔符来标记值。预期输出是当前输出,但需要动态解决方案。我包括 Python 脚本来显示最终结果。为了明确利益冲突,我不会在上面的帖子中使用任何答案,但请您这样做!
XML 输入
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nodes>
<node name="Car" child="Engine"/>
<node name="Car" child="Wheel"/>
<node name="Engine" child="Piston"/>
<node name="Engine" child="Carb"/>
<node name="Carb" child="Bolt"/>
<node name="Spare Wheel"/>
<node name="Bolt" child="Thread"/>
<node name="Carb" child="Foat"/>
<node name="Truck" child="Engine"/>
<node name="Engine" child="Bolt"/>
<node name="Wheel" child="Hubcap"/>
</nodes>
XSLT
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="nodes">
<data>
<xsl:apply-templates select="node[not(@name=ancestor::nodes/node/@child)]"/>
</data>
</xsl:template>
<xsl:template match="node">
<xsl:variable select="@name" name="currname"/>
<xsl:variable select="@child" name="currchild"/>
<xsl:variable select="/nodes/node" name="nodeset1"/>
<xsl:variable select="/nodes/node[@name=$currchild]" name="nodeset2"/>
<xsl:variable select="/nodes/node[@name=$nodeset2/@child]" name="nodeset3"/>
<xsl:variable select="/nodes/node[@name=$nodeset3/@child]" name="nodeset4"/>
<xsl:for-each select="$nodeset2">
<xsl:variable select="@child" name="nodeset2child"/>
<xsl:for-each select="$nodeset3">
<xsl:variable select="@child" name="nodeset3child"/>
<xsl:if test="@name=$nodeset2child">
<xsl:for-each select="$nodeset4">
<xsl:if test="@name=$nodeset3child">
<xsl:value-of select="$currname"/> --> <xsl:value-of select="$currchild"/> --> <xsl:value-of select="$nodeset2child"/> --> <xsl:value-of select="$nodeset3child"/> --> <xsl:value-of select="@child"/><xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="$nodeset2child!=$nodeset3/@child and $nodeset3child != $nodeset4/@name">
<xsl:value-of select="$currname"/> --> <xsl:value-of select="$currchild"/> --> <xsl:value-of select="$nodeset2child"/> --> <xsl:value-of select="$nodeset3child"/><xsl:text>
</xsl:text>
</xsl:if>
</xsl:if>
</xsl:for-each>
<xsl:if test="not($nodeset2child=$nodeset3/@child or ancestor::nodes/node[@name=$nodeset2child]/@child)">
<xsl:value-of select="$currname"/> --> <xsl:value-of select="$currchild"/> --> <xsl:value-of select="$nodeset2child"/><xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:value-of select="@name[not(ancestor::node/@child=$nodeset2/@name)]"/><xsl:text>
</xsl:text>
</xsl:template>
</xsl:transform>
XML 转换输出
<?xml version='1.0' encoding='UTF-8'?>
<data>Car --> Engine --> Piston
Car --> Engine --> Carb --> Bolt --> Thread
Car --> Engine --> Carb --> Foat
Car --> Engine --> Bolt --> Thread
Car --> Wheel --> Hubcap
Spare Wheel
Truck --> Engine --> Piston
Truck --> Engine --> Carb --> Bolt --> Thread
Truck --> Engine --> Carb --> Foat
Truck --> Engine --> Bolt --> Thread
</data>
Python 脚本(在转换后的输出根节点上运行 xpath)
import lxml.etree as ET
# LOAD XML AND XSL DOCS
dom = ET.parse('Input.xml')
xslt = ET.parse('XSLTScript.xsl')
# TRANSFORM XML
transform = ET.XSLT(xslt)
newdom = transform(dom)
# XPATH NEW DOM ROOT NODE (<data>)
print(newdom.xpath('/data')[0].text.replace("\n\n", "\n"))
# Car --> Engine --> Piston
# Car --> Engine --> Carb --> Bolt --> Thread
# Car --> Engine --> Carb --> Foat
# Car --> Engine --> Bolt --> Thread
# Car --> Wheel --> Hubcap
# Spare Wheel
# Truck --> Engine --> Piston
# Truck --> Engine --> Carb --> Bolt --> Thread
# Truck --> Engine --> Carb --> Foat
# Truck --> Engine --> Bolt --> Thread
最佳答案
这是一个更短(23 行)且高效的解决方案
这也是计算上最简单的一个——比较嵌套级别 1 和嵌套级别 3 - 4 ...
此解决方案是尾递归,这意味着任何好的 XSLT 处理器都会通过迭代对其进行优化,从而避免堆栈溢出的可能性,因为最大调用堆栈深度保持不变 (1):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kNodeByChild" match="node" use="@child"/>
<xsl:key name="kNodeByName" match="node" use="@name"/>
<xsl:template match="/*">
<xsl:apply-templates select="node[not(key('kNodeByChild', @name))]"/>
</xsl:template>
<xsl:template match="node[not(key('kNodeByName', @child))]">
<xsl:param name="pParentPath"/>
<xsl:value-of select="concat($pParentPath, @name, ' ---> ', @child, '
')"/>
</xsl:template>
<xsl:template match="node">
<xsl:param name="pParentPath"/>
<xsl:apply-templates select="key('kNodeByName', @child)">
<xsl:with-param name="pParentPath" select="concat($pParentPath, @name, ' ---> ')"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<nodes>
<node name="Car" child="Engine"/>
<node name="Car" child="Wheel"/>
<node name="Engine" child="Piston"/>
<node name="Engine" child="Carb"/>
<node name="Carb" child="Bolt"/>
<node name="Spare Wheel"/>
<node name="Bolt" child="Thread"/>
<node name="Carb" child="Foat"/>
<node name="Truck" child="Engine"/>
<node name="Engine" child="Bolt"/>
<node name="Wheel" child="Hubcap"/>
</nodes>
产生了想要的、正确的结果:
Car ---> Engine ---> Piston
Car ---> Engine ---> Carb ---> Bolt ---> Thread
Car ---> Engine ---> Carb ---> Foat
Car ---> Engine ---> Bolt ---> Thread
Car ---> Wheel ---> Hubcap
Spare Wheel --->
Truck ---> Engine ---> Piston
Truck ---> Engine ---> Carb ---> Bolt ---> Thread
Truck ---> Engine ---> Carb ---> Foat
Truck ---> Engine ---> Bolt ---> Thread
关于xml - XSLT 递归父/子组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37382172/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
给定一个数组a,什么是实现其组合直到第n的最佳方法?例如:a=%i[abc]n=2#Expected=>[[],[:a],[:b],[:c],[:a,b],[:b,:c],[:c,:a]] 最佳答案 做如下:a=%w[abc]n=30.upto(n).flat_map{|i|a.combination(i).to_a}#=>[[],["a"],["b"],["c"],["a","b"],#["a","c"],["b","c"],["a","b","c"]] 关于ruby-最多n的组合,我
我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj
我经常迷上ruby的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情
我想合并多个事件记录关系例如,apple_companies=Company.where("namelike?","%apple%")banana_companies=Company.where("namelike?","%banana%")我想结合这两个关系。不是合并,合并是apple_companies.merge(banana_companies)=>Company.where("namelike?andnamelike?","%apple%","%banana%")我要Company.where("名字像?还是名字像?","%apple%","%banana%")之后,我会写代
我有这个ruby代码:defget_sumnreturn0ifn似乎正在为999之前的值工作。当我尝试9999时,它给了我这个:stackleveltoodeep(SystemStackError)所以,我添加了这个:RubyVM::InstructionSequence.compile_option={:tailcall_optimization=>true,:trace_instruction=>false}但什么也没发生。我的ruby版本是:ruby1.9.3p392(2013-02-22revision39386)[x86_64-darwin12.2.1]我还增加了机器的堆栈大
我有一个熟悉的问题,看起来像是数学世界的排列/组合。如何通过ruby实现以下目标?badges="1-2-3"badge_cascade=[]badges.split("-").eachdo|b|badge_cascade["1","2","3"]ButIwantittobeis:=>["1","2","3","1-2","2-3","3-1","2-1","3-2","1-3","1-2-3","2-3-1","3-1-2"] 最佳答案 函数式方法:bs="1-2-3".split("-")strings=1.upto(bs.
我想禁用HTTP参数的自动XML解析。但我发现命令仅适用于Rails2.x,它们都不适用于3.0:config.action_controller.param_parsers.deleteMime::XML(application.rb)ActionController::Base.param_parsers.deleteMime::XMLRails3.0中的等价物是什么? 最佳答案 根据CVE-2013-0156的最新安全公告你可以将它用于Rails3.0。3.1和3.2ActionDispatch::ParamsParser::
在尝试解决“网格上的路径”问题时,我编写了代码defpaths(n,k)p=(1..n+k).to_ap.combination(n).to_a.sizeend代码工作正常,例如ifn==8andk==2代码返回45,这是正确的路径数。但是,当使用较大的数字时,代码非常慢,我正在努力想出如何加快这个过程。 最佳答案 与其构建组合数组只是为了计算它,不如编写function定义组合的数量。我敢肯定还有包含此功能和许多其他组合函数的gem。请注意,我使用的是gemDistribution对于Math.factorial方法,但这是另一种
对于一个电子商务应用程序,我试图将选项的散列(每个选项都有一系列选择)转换为代表这些选择组合的散列数组。例如:#Input:{:color=>["blue","grey"],:size=>["s","m","l"]}#Output:[{:color=>"blue",:size=>"s"},{:color=>"blue",:size=>"m"},{:color=>"blue",:size=>"m"},{:color=>"grey",:size=>"s"},{:color=>"grey",:size=>"m"},{:color=>"grey",:size=>"m"}]Input内部可能有额