如何从一组 XPath 表达式生成 XML 文件? [英] How to Generate an XML File from a set of XPath Expressions?
问题描述
我希望能够在给定一组 XPath 映射的情况下生成一个完整的 XML 文件.
I want to be able to generate a complete XML file, given a set of XPath mappings.
输入可以指定为两种映射:(1) 一种列出 XPath 表达式和值;(2) 另一个定义了适当的命名空间.
The input could specified in two mappings: (1) One which lists the XPath expressions and values; and (2) the other which defines the appropriate namespaces.
/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 属性 表达式.例如:我应该也能处理属性,比如:
Note also, that it is important that I also deal with XPath Attributes expressions as well. For example: I should also be able to handle attributes, such as:
/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:这是对之前的问题提出的更详细的问题,尽管由于一系列进一步的要求和说明,建议我提出更广泛的问题以满足我的需求.
PS: This is a more detailed question to a previous question asked, although due to a series of further requirements and clarifications, I was recommended to ask a more broader question in order to address my needs.
另请注意,我是在 Java 中实现的.因此,无论是基于 Java 还是基于 XSLT 的解决方案都是完全可以接受的.谢谢.
Note also, I am implementing this in Java. So either a Java-based or XSLT-based solution would both be perfectly acceptable. thnx.
进一步说明:我真的在寻找通用解决方案.上面显示的 XML 只是一个示例.
Further note: I am really looking for a generic solution. The XML shown above is just an example.
推荐答案
如果基于 这个问题有一个简单的解决方案上一个问题的解决方法:
<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>
说明:
一个合理的假设是,在整个生成的文档中,具有相同
local-name()
的任何两个元素都属于同一个命名空间——这涵盖了现实世界的主要部分XML 文档.
A reasonable assumption is made that throughout the generated document any two elements with the same
local-name()
belong to the same namespace -- this covers the predominant majority of real-world XML documents.
命名空间规范遵循路径规范.nsmespace 规范具有以下形式:<namespace of="target element's local-name" prefix="wanted prefix" url="namespace-uri"/>
The namespace specifications follow the path specifications. A nsmespace specification has the form: <namespace of="target element's local-name" prefix="wanted prefix" url="namespace-uri"/>
在使用 xsl:element
生成元素之前,使用由 xsl:key
创建的索引选择适当的命名空间规范.从这个命名空间规范中,它的 prefix
和 url
属性的值用于在 xsl:element
指令中指定完整元素名称的值和元素的命名空间-uri.
Before generating an element with xsl:element
, the appropriate namespace specification is selected using an index created by an xsl:key
. From this namespace specification the values of its prefix
and url
attributes are used in specifying in the xsl:element
instruction the values of the full element name and the element's namespace-uri.
这篇关于如何从一组 XPath 表达式生成 XML 文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!