是否有人能够在使用JAXB编组对象的过程中删除未使用的命名空间?以下是所请求功能的链接:https://github.com/javaee/jaxb-v2/issues/103(请参阅说明)
是否有为此配置JAXB的属性? 这是在MOXy中修复的吗?
我目前正在遍历需要编组的对象,并提取需要绑定到Class[] classesToBeBound
的所有类。
然后我创建了一个新的JAXBContext.newInstance(classesToBeBound)
现在未使用的命名空间不包含在XML中。
我知道即使使用未使用的命名空间,xml验证也是有效的,但对我来说这是框架应该处理的内容。
以下链接https://blogs.oracle.com/enterprisetechtips/entry/customizing_jaxb提到了各种修复(在某处看到文本的中间部分)但是当试图在这些链接中找到解决方案时,链接被破坏或没有人真正解决它。
欢迎任何评论。
(编辑) 纯文字:
GIVEN
a new instance of JAXBContext and add 2 classes with each a separate namespace.
什么时候
marshalling a class that has these 2 classes as a property but only 1 of them is not null
然后
I expect only the namespace of the property that is not null to be visible in the XML.
但是ACTUAL是
that both namespaces are in the xml.
所以我的问题是如何删除或告诉JAXB不要写未使用的命名空间?
把它放在java代码中: GIVEN
public class Foo{
private Bar bar; //namespace something2
private User user; //namespace user
}
当
JAXBContext c = JAXBContext.newInstance(Foo.class, Bar.class, User.class);
...
Foo foo = new Foo();
foo.setBar(null);
foo.setUser(new User("Bob"));
marshaller.umarshal(foo);
那我希望xml是
<foo xmlns="something1" xmlns:user="user">
<user:name>Bob</user:name>
</foo>
但是ACTUAL是(请注意something2名称空间)
<foo xmlns="something1" xmlns:user="user" xmlns:bar="something2">
<user:name>Bob</user:name>
</foo>
当然这是一个简化的例子,我们的类型规范有大约30个不同的命名空间。
答案 0 :(得分:1)
据我所知,这在JAXB中实际上是不可能的-实际上是一个众所周知的问题。如您所见,产生的名称空间列表是在JAXBContext中已注册的名称空间,而不是编组时有效使用的的名称空间:-(< / p>
过去,我使用了与您相同的解决方法(标识各种使用的类,并将JAXBContext缩小为该有限的类集)。
另一个典型的解决方法是分两步处理:首先使用JAXB进行编组,然后进行XSLT转换以摆脱“污染”命名空间的说法。
答案 1 :(得分:0)
是的,可以省略它们。我不确定我是否理解你正确面对的问题。但是没有命名空间的对象编组没有问题。
答案 2 :(得分:0)
这可能是不可能的,因为在对象层次结构的编组发生时,在创建根标记时,关于哪些对象为空v / s非空的信息可能不可用。任何提前获得此信息的尝试也可能具有与之相关的副作用,因为调用了相应的访问器方法。因此,JAXB将静态使用来自JAXBContext的信息来填充此信息。
答案 3 :(得分:0)
您可以尝试使用其他Option Explicit
Sub check()
'First lets store the mandatory items
Dim Mandatory As New Scripting.Dictionary 'You need Microsoft Scripting Runtime library under tools-->references
Dim arr As Variant
Dim i As Long
arr = Workbooks("Book3.xlsx").Sheets("Sheet1").UsedRange.Value 'store the sheet inside the array
For i = 2 To UBound(arr) 'loop through the data and store the mandatory items
If arr(i, 1) = vbNullString Then Exit For 'force an exit if the row has an empty value on column A
If arr(i, 2) = "Yes" Then 'if the item is mandatory, store it
Mandatory.Add arr(i, 1), 1
End If
Next i
'lets check every item in the book2
'For this one to work properly you MUST not have empty rows, the UsedRange must be the same as rows you have
'When having data and then clearing it, the usedrange remains the same, you must delete the empty rows.
Dim j As Long
Dim Header As String
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:="C:\Users\A9905681\Desktop\XY's\Wk 10\Test_Mandatory\Book2.xlsx", ReadOnly:=True, UpdateLinks:=False)
arr = wb.Sheets("Sheet1").UsedRange.Value
'Loop through columns and rows
For j = 1 To UBound(arr, 2) 'loop through columns
Header = arr(1, i)
If Mandatory.Exists(Header) Then 'will loop only through mandatory items
For i = 2 To UBound(arr) 'loop through rows
If arr(i, j) = vbNullString Then 'once we find one item not filled
ThisWorkbook.Sheets("Sheet1").Cells(1, 2) = "Fail" 'fill the cell with fail
Exit Sub 'end the procedure
End If
Next i
End If
Next j
ThisWorkbook.Sheets("Sheet1").Cells(1, 2) = "Pass" 'if nothing happens above, we put Pass to the cell
wb.Close
End Sub
实现。
例如javax.xml.bind.Marshaller
实现很好地处理了这种情况,并在编组对象时删除了所有不必要的名称空间。
要这样做,您需要执行以下步骤:
org.eclipse.persistence.jaxb.JAXBMarshaller
。如果您使用的是 gradle ,则可以将org.eclipse.persistence.jaxb.JAXBMarshaller
添加到依赖项中。compile 'org.eclipse.persistence:eclipselink:2.6.5'
文件(以下问题中的示例jaxb.properties
,在其中一个类JAXBContext c = JAXBContext.newInstance(Foo.class, Bar.class, User.class);
的程序包中) ,Foo
或Bar
)。User
文件中,添加跟随属性,该属性指定所需的上下文工厂:jaxb.properties
这样做,javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
将被用作运行时的org.eclipse.persistence.jaxb.JAXBMarshaller
实现。然后,在编组对象时不会出现不必要的名称空间。
答案 4 :(得分:0)
我尝试了该线程中建议的解决方案albciff,事实证明Eclipse Moxy比参考实现(org.glassfish.jaxb)处理得更好。 这是有关如何切换到JAXB的Moxy实现的信息: https://wiki.eclipse.org/EclipseLink/Examples/MOXy/JAXB/SpecifyRuntime
文档中没有指定它,但是您也可以仅使用一个配置文件来更改jaxb的实现,而不是在存在jaxb注释类的每个包中更改jaxb.properties。只需创建一个文件META-INF/services/javax.xml.bind.JAXBContext
(是非常规文件名),其内容如下:
org.eclipse.persistence.jaxb.JAXBContextFactory
这使得jaxb ContextFinder
对JVM中的所有jaxb编组使用Eclipse Moxy实现。
另一种选择是使用系统属性-Djavax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
免责声明:不会为当前有效负载最小化/优化名称空间声明,但是至少它不包括jaxb语法一部分的所有名称空间。我正在进行的集成从一个惊人的700多个声明的名称空间(每个已发送消息大约60KB的无用开销)到一条消息中最多3个声明。尽管对于其中具有许多不同类型的消息,将声明在该特定消息中有效的所有名称空间。这意味着在某些情况下,当只有一个足以满足当前有效负载时,我仍然可以获得约30个声明的命名空间。
我想,如果您需要优化带宽,那么SOAP并不是可行的方法。
答案 5 :(得分:-1)
尝试这样的方法marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION,“不需要名称空间的类”);在你的情况下应该是 marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION,bar.class);