选择儿童

时间:2014-10-14 21:07:29

标签: xml xpath

我正在解析xml文档以加载到另一个系统。我遇到过XML文件的问题,这个问题已经引发了一些问题。

xml文件如下所示:

<Project:Application  
xmlns:Budget="http://com.gff/Budget"   
xmlns:Budget1="http://com.gff/Budget123"   
xmlns:Project="http://com.gff/Project"   
xmlns:header="http://com.gff/Header">   
<header:SubmissionHeader>  
    <header:Name>Application Name</header:Name>  
    <header:Number>PRJ12345</header:Number>  
    <header:Title>XML File Parse</header:Title>  
</header:SubmissionHeader>  
<Project:Forms>  
    <Budget123:Budget123>  
        <Budget1:ID>12345</Budget1:ID>  
        <Budget1:Type>Project A</Budget1:Type>  
    </Budget123:Budget123>  
    <Budget123:Budget123>  
        <Budget1:ID>6789</Budget1:ID>  
        <Budget1:Type>Project B</Budget1:Type>  
    </Budget123:Budget123>  
    <Budget123:Budget123>  
        <Budget1:ID>01234</Budget1:ID>  
        <Budget1:Type>Project C</Budget1:Type>  
    </Budget123:Budget123>  
</Project:Forms>  

以下是我执行的将数据转换为变量并通过Web服务加载到我的应用程序的代码:

<gel:script 
xmlns:core="jelly:core"  
xmlns:j="jelly.core"  
xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"  
xmlns:x="jelly:org.apache.commons.jelly.tags.xml.XMLTagLibrary"  
xmlns:util="jelly:util"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- *************************************************************  -->
<!-- Program:  Parse XML Application                                -->
<!-- ************************************************************   -->
<gel:log message="Start Xml File Parse Test" />  
<x:parse var="RemoveNameSpace">  
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
        <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>  
        <xsl:template match="*">  
            <xsl:element name="{local-name()}">  
                <xsl:apply-templates select="@* | node()"/>  
            </xsl:element>  
        </xsl:template>  
        <xsl:template match="@*">  
            <xsl:attribute name="{local-name()}">  
                <xsl:value-of select="."/>  
            </xsl:attribute>  
        </xsl:template>  
        <xsl:template match="comment() | text() | processing-instruction()">  
            <xsl:copy/>  
        </xsl:template>  
    </xsl:stylesheet>  
</x:parse>  
<x:parse var="xmlRawData" xml="file:///C:/Users/admin/Desktop/Application.xml"  />  
<x:transform var="xmlData" xml= "${xmlRawData}" xslt="${RemoveNameSpace}" />  
<gel:log message="${xmlData.asXML()}" />  
<gel:parse var="gelXmlData">  
    <x:transform xml= "${xmlRawData}" xslt="${RemoveNameSpace}" />  
</gel:parse>  
<gel:set asString="true" select="$gelXmlData//Application/SubmissionHeader/Name/text()" var="Name"/>
<gel:set asString="true" select="$gelXmlData//Application/@Forms/text()" var="Budget"/>
<gel:log>
  Name = ${Name}
  Budget = ${Budget}
</gel:log>
</gel:script>

问题在于,对于预算部分,每个文件的名称看起来都不同。例如,此文件的节点名称为Budget123,下一个文件具有Budget10,下一个文件为Budget_12。似乎没有押韵或理由为什么命名空间是它们的方式。我想要遍历树,获取每个节点,并将它们放入变量,然后用变量的名称替换以获取值,而不是硬编码获取值的路径。

我试过了:

//Application/Forms/*[starts-with(local-name(),'Budget')] 

问题是返回:

<Budget123:Budget123>  
        <Budget1:ID>12345</Budget1:ID>  
        <Budget1:Type>Project A</Budget1:Type>  
    </Budget123:Budget123>  
    <Budget123:Budget123>  
        <Budget1:ID>6789</Budget1:ID>  
        <Budget1:Type>Project B</Budget1:Type>  
    </Budget123:Budget123>  
    <Budget123:Budget123>  
        <Budget1:ID>01234</Budget1:ID>  
        <Budget1:Type>Project C</Budget1:Type>  
    </Budget123:Budget123>  
</Project:Forms>  

我只想要节点名称,而不是其他所有东西,所以:Budget123,或者它最终的结果。

select="$gelXmlData//Application/Forms/*[starts-with(local-name(),'Budget')]/ID/text()" var="ID"

上面的代码确实可以获取节点预算的值,但与此同时,我想让它足够动态,不要总是从预算开始依赖它。

1 个答案:

答案 0 :(得分:0)

首先,输入XML中的前缀Budget123未绑定,并且未使用</Project:Application>正确关闭。

我不确定我是否理解您输出的内容,但我会尝试一下:

//Application/Forms/*[starts-with(local-name(),'Budget')]/local-name()

结果将是

Budget123 Budget123 Budget123

注意:此路径出现的行为取决于您使用的XPath版本。我假设您使用的是XPath 2.0。否则,你需要像

这样的东西
local-name(//Application/Forms/*[starts-with(local-name(),'Budget')])

但是,这只会产生找到的第一个元素的名称。


如果这涵盖了Forms的所有子元素,则可以使用

//Application/Forms/*/local-name()

独立于名称空间的版本:

//*[local-name()='Application']/*[local-name()='Forms']/*[starts-with(local-name(),'Budget')]/local-name()"