当前位置: 首页 > 面试题库 >

如何从一组XPath表达式生成XML文件?

子车桐
2023-03-14
问题内容

给定一组XPath映射,我希望能够生成一个完整的XML文件。

输入可以在两个映射中指定:(1)列出XPath表达式和值的映射;(2)另一个定义了适当的名称空间。

/create/article[1]/id                 => 1
/create/article[1]/description        => bar
/create/article[1]/name[1]            => foo
/create/article[1]/price[1]/amount    => 00.00
/create/article[1]/price[1]/currency  => USD
/create/article[2]/id                 => 2
/create/article[2]/description        => some name
/create/article[2]/name[1]            => some description
/create/article[2]/price[1]/amount    => 00.01
/create/article[2]/price[1]/currency  => USD

对于命名空间:

/create               => xmlns:ns1='http://predic8.com/wsdl/material/ArticleService/1/
/create/article       => xmlns:ns1='http://predic8.com/material/1/‘
/create/article/price => xmlns:ns1='http://predic8.com/common/1/‘
/create/article/id    => xmlns:ns1='http://predic8.com/material/1/'

还要注意,同样重要的是,我还必须处理XPath Attributes 表达式。例如:我也应该能够处理属性,例如:

/create/article/@type => richtext

最终输出应如下所示:

<ns1:create xmlns:ns1='http://predic8.com/wsdl/material/ArticleService/1/'>
    <ns1:article xmlns:ns1='http://predic8.com/material/1/‘ type='richtext'>
        <name>foo</name>
        <description>bar</description>
        <ns1:price xmlns:ns1='http://predic8.com/common/1/'>
            <amount>00.00</amount>
            <currency>USD</currency>
        </ns1:price>
        <ns1:id xmlns:ns1='http://predic8.com/material/1/'>1</ns1:id>
    </ns1:article>
    <ns1:article xmlns:ns1='http://predic8.com/material/2/‘ type='richtext'>
        <name>some name</name>
        <description>some description</description>
        <ns1:price xmlns:ns1='http://predic8.com/common/2/'>
            <amount>00.01</amount>
            <currency>USD</currency>
        </ns1:price>
        <ns1:id xmlns:ns1='http://predic8.com/material/2/'>2</ns1:id>
    </ns1:article>
</ns1:create>

PS:这是对先前提出的问题的更详细的问题,尽管由于一系列进一步的要求和说明,建议我提出一个更广泛的问题以解决我的需求。

还要注意,我正在Java中实现它。因此,基于Java的解决方案或基于XSLT的解决方案都可以完全接受。thnx。

进一步说明:我真的在寻找 通用 解决方案。上面显示的XML只是一个示例


问题答案:

如果
以先前问题的解决方案为
基础,则可以轻松解决此问题:

<xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:my="my:my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>

     <xsl:key name="kNSFor" match="namespace" use="@of"/>
     <xsl:variable name="vStylesheet" select="document('')"/>

     <xsl:variable name="vPop" as="element()*">
        <item path="/create/article/@type">richtext</item>
        <item path="/create/article/@lang">en-us</item>
        <item path="/create/article[1]/id">1</item>
        <item path="/create/article[1]/description">bar</item>
        <item path="/create/article[1]/name[1]">foo</item>
        <item path="/create/article[1]/price[1]/amount">00.00</item>
        <item path="/create/article[1]/price[1]/currency">USD</item>
        <item path="/create/article[1]/price[2]/amount">11.11</item>
        <item path="/create/article[1]/price[2]/currency">AUD</item>
        <item path="/create/article[2]/id">2</item>
        <item path="/create/article[2]/description">some name</item>
        <item path="/create/article[2]/name[1]">some description</item>
        <item path="/create/article[2]/price[1]/amount">00.01</item>
        <item path="/create/article[2]/price[1]/currency">USD</item>

        <namespace of="create" prefix="ns1:"
                   url="http://predic8.com/wsdl/material/ArticleService/1/"/>
        <namespace of="article" prefix="ns1:"
                   url="xmlns:ns1='http://predic8.com/material/1/"/>
        <namespace of="@lang" prefix="xml:"
                   url="http://www.w3.org/XML/1998/namespace"/>
        <namespace of="price" prefix="ns1:"
                   url="xmlns:ns1='http://predic8.com/material/1/"/>
        <namespace of="id" prefix="ns1:"
                   url="xmlns:ns1='http://predic8.com/material/1/"/>
     </xsl:variable>

     <xsl:template match="/">
      <xsl:sequence select="my:subTree($vPop/@path/concat(.,'/',string(..)))"/>
     </xsl:template>

     <xsl:function name="my:subTree" as="node()*">
      <xsl:param name="pPaths" as="xs:string*"/>

      <xsl:for-each-group select="$pPaths" group-adjacent=
            "substring-before(substring-after(concat(., '/'), '/'), '/')">
        <xsl:if test="current-grouping-key()">
         <xsl:choose>
           <xsl:when test=
              "substring-after(current-group()[1], current-grouping-key())">

             <xsl:variable name="vLocal-name" select=
              "substring-before(concat(current-grouping-key(), '['), '[')"/>

             <xsl:variable name="vNamespace"
                           select="key('kNSFor', $vLocal-name, $vStylesheet)"/>


             <xsl:choose>
              <xsl:when test="starts-with($vLocal-name, '@')">
               <xsl:attribute name=
                 "{$vNamespace/@prefix}{substring($vLocal-name,2)}"
                    namespace="{$vNamespace/@url}">
                 <xsl:value-of select=
                  "substring(
                       substring-after(current-group(), current-grouping-key()),
                       2
                             )"/>
               </xsl:attribute>
              </xsl:when>
              <xsl:otherwise>
               <xsl:element name="{$vNamespace/@prefix}{$vLocal-name}"
                          namespace="{$vNamespace/@url}">

                    <xsl:sequence select=
                     "my:subTree(for $s in current-group()
                                  return
                                     concat('/',substring-after(substring($s, 2),'/'))
                                   )
                     "/>
                 </xsl:element>
              </xsl:otherwise>
             </xsl:choose>
           </xsl:when>
           <xsl:otherwise>
            <xsl:value-of select="current-grouping-key()"/>
           </xsl:otherwise>
         </xsl:choose>
         </xsl:if>
      </xsl:for-each-group>
     </xsl:function>
</xsl:stylesheet>

当此转换应用于任何XML文档(未使用)时,将产生所需的正确结果

<ns1:create xmlns:ns1="http://predic8.com/wsdl/material/ArticleService/1/">
   <ns1:article xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/" type="richtext"
                xml:lang="en-us"/>
   <ns1:article xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/">
      <ns1:id>1</ns1:id>
      <description>bar</description>
      <name>foo</name>
      <ns1:price>
         <amount>00.00</amount>
         <currency>USD</currency>
      </ns1:price>
      <ns1:price>
         <amount>11.11</amount>
         <currency>AUD</currency>
      </ns1:price>
   </ns1:article>
   <ns1:article xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/">
      <ns1:id>2</ns1:id>
      <description>some name</description>
      <name>some description</name>
      <ns1:price>
         <amount>00.01</amount>
         <currency>USD</currency>
      </ns1:price>
   </ns1:article>
</ns1:create>

说明

  1. 可以合理地假设,在整个生成的文档中,具有相同元素的任何两个元素都local-name()属于同一名称空间-这涵盖了现实世界中XML文档的绝大多数。

  2. 名称空间规范遵循路径规范。nsmespace规范具有以下形式:<namespace of="target element's local-name" prefix="wanted prefix" url="namespace-uri"/>

  3. 在使用生成元素之前xsl:element,使用xsl:key。创建的索引选择适当的名称空间规范。根据此名称空间规范,其值prefixurl属性用于在xsl:element指令中指定完整元素名称和元素的namespace-uri的值。



 类似资料:
  • 问题内容: 考虑我有以下示例XML文件: 将其扁平化为一组xpath表达式的最佳(最有效)方法是什么。另请注意:我想忽略任何名称空间和属性信息。(如果需要,也可以将其作为预处理步骤来完成)。 所以我想作为输出: 我正在用Java实现。 编辑: PS,在文本节点上没有数据的情况下,我也可能需要此方法,因此,例如,以下代码应生成与上述相同的输出: 问题答案: 您可以使用XSLT轻松完成此操作。查看示例

  • 问题内容: 从XPath表达式的映射填充(或生成)XML模板文件的最佳方法是什么? 要求是我们需要从模板开始(因为它可能包含XPath表达式中未捕获的信息)。 例如,起始模板可能是: 然后提供给我们,类似于: 然后,我们应该生成: 我是用Java实现的,尽管如果可能的话,我会首选基于XSLT的解决方案。 问题答案: 此转换从“表达式”创建具有所需结果结构的XML文档-仍需将其转换为最终结果: 当此

  • 问题内容: 我是JAXB的新手,并且想知道是否有一种方法可以使用xpath表达式将XML解组到我的响应对象。问题是我正在呼叫第三方Web服务,收到的响应有很多详细信息。我不希望将XML中的所有详细信息映射到我的响应对象。我只希望从xml映射一些细节,使用这些细节我可以使用特定的XPath表达式并将其映射到我的响应对象。有没有注释可以帮助我实现这一目标? 例如考虑以下响应 我只对检索街道名称感兴趣,

  • 我是JAXB新手,想知道是否有一种方法可以使用xpath表达式将XML解组到响应对象。问题是我正在呼叫第三方Web服务,我收到的回复有很多详细信息。我不希望将XML中的所有细节映射到我的响应对象。我只希望映射xml中的一些细节,使用特定的XPath表达式可以获得这些细节,并将其映射到响应对象。有没有注释可以帮助我实现这一点? 例如,考虑以下响应 我只对检索街道名称感兴趣,所以我想使用xpath表达

  • 问题内容: 是的,您没看错。我需要能够从正则表达式 生成 随机文本的内容。因此,文本应该是随机的,但要与正则表达式匹配。看来它不存在,但我可能是错的。 仅举一个例子:该库将能够以“ ”作为输入,并生成诸如以下示例: abc abbbc bac 等等 更新:我自己创建了一些东西:Xeger。查看http://code.google.com/p/xeger/。 问题答案: 我刚刚创建了一个库来进行此操

  • 主要内容:示例XPath表达式通常定义模式以便选择一组节点。 这些模式由XSLT用于执行转换,或者由用于寻址。 XPath规范指定了七种类型的节点,这些节点可以是XPath表达式的执行输出。 根 元素 文本 属性 注释 处理指令 命名空间 XPath使用路径表达式从XML文档中选择节点或节点列表。 以下是从XML文档中选择节点/节点列表的路径和表达式列表。 序号 表达式 描述 1 选择具有给定名称的所有节点。