如何使用JQuery扁平化XML树?

时间:2019-12-21 06:24:41

标签: javascript jquery xml

我的食品开发应用程序要求将XML树压平。听起来很简单,但我遇到了麻烦。该算法要求所有<stream>...</stream>节点和一个子<disposition>Break out overall</disposition>节点到顶层<root>...</root>节点。

之前:

<root>
    <stream>
        <name>Corn Oil</name>
        <quantity>0.3</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Potatoes</name>
        <quantity>0.5</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Seasoning</name>
        <quantity>0.1</quantity>
        <disposition>Break out overall</disposition>
        <isstream>true</isstream>
        <stream>
            <name>Salt</name>
            <quantity>0.02</quantity>
            <disposition>Break out overall</disposition>
        </stream>
        <stream>
            <name>Maltodextrin</name>
            <quantity>0.03</quantity>
            <disposition>Break out overall</disposition>
        </stream>
        <stream>
            <name>Spice Blend</name>
            <quantity>0.04</quantity>
            <disposition>Break out overall</disposition>
            <isstream>true</isstream>
            <stream>
                <name>Black Pepper</name>
                <quantity>0.02</quantity>
                <disposition>Break out overall</disposition>
            </stream>
            <stream>
                <name>Garlic</name>
                <quantity>0.02</quantity>
                <disposition>Break out overall</disposition>
            </stream>
            <stream>
                <name>Red Pepper</name>
                <quantity>0.02</quantity>
                <disposition>Break out overall</disposition>
            </stream>
        </stream>
    </stream>
</root>

算法后的预期结果:

<root>
    <stream>
        <name>Corn Oil</name>
        <quantity>0.3</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Potatoes</name>
        <quantity>0.5</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Seasoning</name>
        <quantity>0.1</quantity>
        <disposition>Break out overall</disposition>
        <isstream>true</isstream>
    </stream>
    <stream>
        <name>Salt</name>
        <quantity>0.02</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Maltodextrin</name>
        <quantity>0.03</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Spice Blend</name>
        <quantity>0.04</quantity>
        <disposition>Break out overall</disposition>
        <isstream>true</isstream>
    </stream>
    <stream>
        <name>Black Pepper</name>
        <quantity>0.02</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Garlic</name>
        <quantity>0.02</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Red Pepper</name>
        <quantity>0.02</quantity>
        <disposition>Break out overall</disposition>
    </stream>
</root>

实际结果:

<root>
    <stream>
        <name>Corn Oil</name>
        <quantity>0.3</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Potatoes</name>
        <quantity>0.5</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Seasoning</name>
        <quantity>0.1</quantity>
        <disposition>Break out overall</disposition>
        <isstream>true</isstream>
        <stream>
            <name>Salt</name>
            <quantity>0.02</quantity>
            <disposition>Break out overall</disposition>
        </stream>
        <stream>
            <name>Maltodextrin</name>
            <quantity>0.03</quantity>
            <disposition>Break out overall</disposition>
        </stream>
        <stream>
            <name>Spice Blend</name>
            <quantity>0.04</quantity>
            <disposition>Break out overall</disposition>
            <isstream>true</isstream>
            <stream>
                <name>Black Pepper</name>
                <quantity>0.02</quantity>
                <disposition>Break out overall</disposition>
            </stream>
            <stream>
                <name>Garlic</name>
                <quantity>0.02</quantity>
                <disposition>Break out overall</disposition>
            </stream>
            <stream>
                <name>Red Pepper</name>
                <quantity>0.02</quantity>
                <disposition>Break out overall</disposition>
            </stream>
        </stream>
    </stream>
    <stream>
        <name>Salt</name>
        <quantity>0.02</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Maltodextrin</name>
        <quantity>0.03</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Spice Blend</name>
        <quantity>0.04</quantity>
        <disposition>Break out overall</disposition>
        <isstream>true</isstream>
        <stream>
            <name>Black Pepper</name>
            <quantity>0.02</quantity>
            <disposition>Break out overall</disposition>
        </stream>
        <stream>
            <name>Garlic</name>
            <quantity>0.02</quantity>
            <disposition>Break out overall</disposition>
        </stream>
        <stream>
            <name>Red Pepper</name>
            <quantity>0.02</quantity>
            <disposition>Break out overall</disposition>
        </stream>
    </stream>
    <stream>
        <name>Black Pepper</name>
        <quantity>0.02</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Garlic</name>
        <quantity>0.02</quantity>
        <disposition>Break out overall</disposition>
    </stream>
    <stream>
        <name>Red Pepper</name>
        <quantity>0.02</quantity>
        <disposition>Break out overall</disposition>
    </stream>
</root>

下面JsFiddle处的算法与顶级流,玉米油,土豆和调味料完全一样,可以按需删除<stream>...</stream>节点下的每个<root>...</root>节点并追加它返回到<root>...</root>节点下。但是,对于公式中的所有其他嵌套<stream>...</stream>节点(香料混合,麦芽糊精,盐,红辣椒,大蒜,黑胡椒),算法的$(this).remove()部分无效,即这些流被复制到<root>...</root>节点,但原始节点未删除。

var xmlAsStr = "<root><stream><name>Corn Oil</name><quantity>0.3</quantity><disposition>Break out overall</disposition></stream><stream><name>Potatoes</name><quantity>0.5</quantity><disposition>Break out overall</disposition></stream><stream><name>Seasoning</name><quantity>0.1</quantity><disposition>Break out overall</disposition><isstream>true</isstream><stream><name>Salt</name><quantity>0.02</quantity><disposition>Break out overall</disposition></stream><stream><name>Maltodextrin</name><quantity>0.03</quantity><disposition>Break out overall</disposition></stream><stream><name>Spice Blend</name><quantity>0.04</quantity><disposition>Break out overall</disposition><isstream>true</isstream><stream><name>Black Pepper</name><quantity>0.02</quantity><disposition>Break out overall</disposition></stream><stream><name>Garlic</name><quantity>0.02</quantity><disposition>Break out overall</disposition></stream><stream><name>Red Pepper</name><quantity>0.02</quantity><disposition>Break out overall</disposition></stream></stream></stream></root>";
    var xmlDoc = $.parseXML( xmlAsStr );
    var $xml = $( xmlDoc );

  $('stream',$xml).each(function(){
      if($(this).children('disposition').text()=="Break out overall" )
    {
       var thisHtml = $(this).html();
      $(this).remove();
      $xml.find('root').append('<stream>'+thisHtml+'</stream>');
    }
  });

除了$(this).remove();之外,我还尝试过: $xml.find('root').find(this).remove(); $xml.find(this).remove(); $(this,$xml).remove(); 但是从XML树中删除这些嵌套节点似乎无济于事。 对于如何完成上述XML操作的任何帮助或见解将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:1)

自下而上的递归算法可以按预期方式平整XML树。我最初的错误是试图仅依靠jQuery隐式迭代和遍历来解决此问题,而无需显式递归。下面提供了已解决的代码以及有效的jsFiddle供您参考。抱歉给您打扰,问题已解决。非常感谢。

$(function(){
    var xmlAsStr = "<root><stream><name>Corn Oil</name><quantity>0.3</quantity><disposition>Break out overall</disposition></stream><stream><name>Potatoes</name><quantity>0.5</quantity><disposition>Break out overall</disposition></stream><stream><name>Seasoning</name><quantity>0.1</quantity><disposition>Break out overall</disposition><isstream>true</isstream><stream><name>Salt</name><quantity>0.02</quantity><disposition>Break out overall</disposition></stream><stream><name>Maltodextrin</name><quantity>0.03</quantity><disposition>Break out overall</disposition></stream><stream><name>Spice Blend</name><quantity>0.04</quantity><disposition>Break out overall</disposition><isstream>true</isstream><stream><name>Black Pepper</name><quantity>0.02</quantity><disposition>Break out overall</disposition></stream><stream><name>Garlic</name><quantity>0.02</quantity><disposition>Break out overall</disposition></stream><stream><name>Red Pepper</name><quantity>0.02</quantity><disposition>Break out overall</disposition></stream></stream></stream></root>"; 
            var xmlDoc = $.parseXML( xmlAsStr );
            var $xml = $( xmlDoc ); 
            var $myResultingXml; 

            var streamNodeArray = []; 

            $('root',$xml).children('stream').each(function(){       
                streamNodeArray.push($(this)); 
            });

            var i = 0; 
            for(i=0;i<streamNodeArray.length;i++)
            {
                $myResultingXml = flattenXmlRecursive(streamNodeArray[i],$xml); 
            }

  var resultingXmlString = '<root>'+$myResultingXml.find("root").html()+'</root>'
  console.log(resultingXmlString );
});

function flattenXmlRecursive(xmlFragment,xmlDoc)
{
    var i = 0; 
    var streamNodeArray = []; 
    xmlFragment.children('stream').each(function(){
        streamNodeArray.push($(this)); 
    });

    for(i=0;i<streamNodeArray.length;i++)
    {
        flattenXmlRecursive(streamNodeArray[i],xmlDoc); 
    }

    if(xmlFragment.children('disposition').text()=='Break out overall')
    {
        xmlDoc.find(xmlFragment).remove(); 
        xmlDoc.find('root').append(xmlFragment); 
    }

    return xmlDoc; 
}